Posts tagged with binary-exploitation

pwnable.tw - applestore

Posted on August 27, 2020* in ctf-writeups

Challenge

tomcr00se rooted the galaxy S5, but we need you to jailbreak the iPhone8!

nc chall.pwnable.tw 10104

We're also given a binary and libc shared executable.

Reversing

When reversing binaries, I usually run the binary and compare its execution alongside the disassemby+pseudocode. When we run the given binary, we're greeted by a menu with 6 options:

Continue Reading

fd - 1pt

Challenge

Mommy! what is a file descriptor in Linux?

ssh fd@pwnable.kr -p2222 (pw:guest)

Source Code

After ssh-ing into the server with the given details, we can view the source code of the challenge by running cat fd.c:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char buf[32];
int main(int argc, char* argv[], char* envp[]){
        if(argc<2){
                printf("pass argv[1] a number\n");
                return 0;
        }
        int fd = atoi( argv[1] ) - 0x1234;
        int len = 0;
        len = read(fd, buf, 32);
        if(!strcmp("LETMEWIN\n", buf)){
                printf("good job :)\n");
                system("/bin/cat flag");
                exit(0);
        }
        printf("learn about Linux file IO\n");
        return 0;
}
Continue Reading

Challenge

Can you see anything?

Get a shell for me.

nc chall.pwnable.tw 10200

seethefile

libc.so

Background

_IO_FILE_plus

Files are internally represented using the _IO_FILE_plus struct in glibc:

struct _IO_FILE_plus
{
  _IO_FILE file;
  const struct _IO_jump_t *vtable;
};
Continue Reading

Challenge

Make tcache great again !

nc chall.pwnable.tw 10207

tcache_tear

libc.so

Background

Per-thread cache (tcache) is an optimization enabled in versions of libc after 2.26. To increase heap performance, security checks are limited within the tcache implementation. Tcache is implemented using two important internal structures:

Continue Reading

Challenge

Please kill the werewolf with silver bullet!

nc chall.pwnable.tw 10103

We are also provided a binary and the libc used on the server.

Solution

When running the binary, we can see that we have four options:

The provided binary was not stripped, so reversing was easy with Ghidra.

void create_bullet(bullet *bullet)
{
  size_t size;
  
  if (bullet->description[0] == '\0') {
    printf("Give me your description of bullet :",0);
    read_input((char *)bullet,0x30);
    size = strlen((char *)bullet);
    printf("Your power is : %u\n",size);
    bullet->power = size;
    puts("Good luck !!");
  }
  else {
    puts("You have been created the Bullet !");
  }
  return;
}
Continue Reading

Challenge

A good Hacker should always take good notes!

nc chall.pwnable.tw 10102

We are also provided a binary and the libc used on the server.

Solution

When running the binary, we can see four options:

Understanding the binary

When reversing the binary, we can use the shown options to help identify functions used. I reversed the binary in Ghidra, and the following are the cleaned up decompilation output from the binary.

Continue Reading

Challenge

We are given a binary to exploit. By running checksec on it, we see that the binary has the following protections: [show-line-numbers]: false

Canary                        : No
NX                            : Yes
PIE                           : Yes
Fortify                       : No
RelRO                         : Partial

Because the binary has NX, we cannot place executable shell code in a buffer and then jump to it. PIE allows the code section of the binary to be located anywhere in memory. This means that we don't know the address of functions within the binary; however, we still know relative offsets.

Reverse Engineering

Dump of assembler code for function main:
   0x0000000000001145 <+0>:     push   rbp                                  # Setup Stack
   0x0000000000001146 <+1>:     mov    rbp,rsp                              
   0x0000000000001149 <+4>:     sub    rsp,0x110                            # Allocate 0x110 bytes on stack
   0x0000000000001150 <+11>:    mov    DWORD PTR [rbp-0x104],edi            # Copies edi into stack offset 0x104
   0x0000000000001156 <+17>:    mov    QWORD PTR [rbp-0x110],rsi            # Copies rsi into stack offset 0x110
   0x000000000000115d <+24>:    mov    rax,QWORD PTR [rbp-0x110]            # Copies value of pointer into rax
   0x0000000000001164 <+31>:    add    rax,0x8                              # Adds size_t
   0x0000000000001168 <+35>:    mov    rdx,QWORD PTR [rax]                  # Copies the value of the pointer [rax + 8] into rdx
   0x000000000000116b <+38>:    lea    rax,[rbp-0x100]                      # Loads the address of [rbp - 0x100] into rax
   0x0000000000001172 <+45>:    mov    rsi,rdx                              # rsi = rdx
   0x0000000000001175 <+48>:    mov    rdi,rax                              # rdi = rax
   0x0000000000001178 <+51>:    call   0x1030 <strcpy@plt>                  # Calls strcpy(rsi, rdi) ; strcpy ([rbp - 0x100], argv[1])
   0x000000000000117d <+56>:    lea    rax,[rbp-0x100]                      # Loads address of [rbp-0x100] into rax
   0x0000000000001184 <+63>:    mov    rdi,rax                              # rdi = rax
   0x0000000000001187 <+66>:    call   0x1040 <puts@plt>                    # puts(rdi)
   0x000000000000118c <+71>:    mov    eax,0x0                              # return 0
   0x0000000000001191 <+76>:    leave                                       
   0x0000000000001192 <+77>:    ret                                         
End of assembler dump.
Continue Reading

pwnable.tw - start

Posted on November 22, 2019* in ctf-writeups

We are given a linux binary. To start off, lets run checksec on it:

Arch:     i386-32-little
RELRO:    No RELRO
Stack:    No canary found
NX:       NX disabled
PIE:      No PIE (0x8048000)

It looks like NX is disabled, so if needed, we can place and execute shell code from the stack. To understand how this binary works, I opened it with Ghidra. There are only two functions, _entry and _exit. Let's look at _entry first. Although the decompilation is mostly useless, the disassembly is more than enough.

We can see two int 0x80s that are syscalls. Looking at the value of eax and by referencing a 32-bit syscall table, we can identify them. The reversed syscalls are shown in comments in the above screenshot. It's also clear that we control EIP due to the large read syscall that will overflow into the save return address on the stack.

As we saw earlier, the NX bit is disabled, so we can jump to our shellcode. To do so, we need to leak a stack address to identify where to jump to. Using pwndbg, it's easy to watch the stack during execution.

Continue Reading

Challenge

This program is quite short, but has got printf and gets in it! This shouldn't be too hard, right?

Connect at nc shell.2019.nactf.com 31283

We are given the libc used, the binary, and the source code.

#include <stdio.h>

void vuln()
{
	char buf[64];
	fputs("Type something>", stdout);
	gets(buf);
	fputs("You typed: ", stdout);
	printf(buf);
}

int main()
{
	/* Disable buffering on stdout */
	setvbuf(stdout, NULL, _IONBF, 0);

	vuln();

	return 0;
}
Continue Reading

Challenge

Read the flag from /home/orw/flag.

Only open read write syscall are allowed to use.

nc chall.pwnable.tw 10001

Solution

The binary simply reads in 200 bytes and then jumps to its address, after using prctl to prevent calling execve:

int main(void) {
  orw_seccomp();
  printf("Give my your shellcode:");
  read(0,shellcode,200);
  (*(code *)shellcode)();
  return 0;
}

By using strace, we see that orw_seccomp calls prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, {len = 12, filter = 0x400000020}).
Based on this and the challenge description, it is clear that we cannot use a execve shell code like in the previous challenge.

To assemble shellcode, I used an online x86 assembler rather than setting up nasm. We know that the flag is located in /home/orw/flag. Our shellcode needs to accomplish the following:

Continue Reading

Problem

As the song draws closer to the end, another executable be-quick-or-be-dead-3 suddenly pops up. This one requires even faster machines. Can you run it fast enough too?

Solution

After decompiling the program with Snowman, we can see pseudocode for the calc function:

uint32_t calc(uint32_t edi) {
    uint32_t eax2;
    uint32_t eax3;
    uint32_t eax4;
    uint32_t eax5;
    uint32_t eax6;
    uint32_t v7;

    if (edi > 4) {
        eax2 = calc(edi - 1);
        eax3 = calc(edi - 2);
        eax4 = calc(edi - 3);
        eax5 = calc(edi - 4);
        eax6 = calc(edi - 5);
        v7 = eax6 * 0x1234 + (eax2 - eax3 + (eax4 - eax5));
    } else {
        v7 = edi * edi + 0x2345;
    }
    return v7;
}
Continue Reading
Switch to Dark Mode
Dark
Switch to Light Mode
Light