Write-ups/pwnable.xyz
xor - pwnable.xyz
dolphinlmg
2020. 2. 11. 23:45
int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
{
int v3; // [rsp+Ch] [rbp-24h]
__int64 v4; // [rsp+10h] [rbp-20h]
__int64 v5; // [rsp+18h] [rbp-18h]
__int64 v6; // [rsp+20h] [rbp-10h]
unsigned __int64 v7; // [rsp+28h] [rbp-8h]
v7 = __readfsqword(0x28u);
puts("The Poopolator");
setup("The Poopolator", argv);
while ( 1 )
{
v6 = 0LL;
printf(format);
v3 = _isoc99_scanf("%ld %ld %ld", &v4, &v5, &v6);
if ( !v4 || !v5 || !v6 || v6 > 9 || v3 != 3 )
break;
result[v6] = v5 ^ v4;
printf("Result: %ld\n", result[v6]);
}
exit(1);
}
숫자 세개를 입력받는데 모두 0이 아니고 v6는 9보다 커야한다.
.text:0000000000000AB3 mov rax, [rbp+var_10]
.text:0000000000000AB7 cmp rax, 9
.text:0000000000000ABB jg short loc_AC3
v6가 음수여도 조건문을 통과할 수 있다. 그렇게 되면 result보다 아래에 있는 영역에 접근 할 수 있는데, Full RELRO와 PIE가 걸려있어 GOT Overwrite도 불가능하다. 일단 gdb에서 vmmap을 확인해 봤다.
pwndbg> vmmap
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
0x555555554000 0x555555555000 rwxp 1000 0 /home/dpster/Desktop/Pwnable/pwnable_xyz/xor/image/challenge/challenge
0x555555755000 0x555555756000 r--p 1000 1000 /home/dpster/Desktop/Pwnable/pwnable_xyz/xor/image/challenge/challenge
0x555555756000 0x555555757000 rw-p 1000 2000 /home/dpster/Desktop/Pwnable/pwnable_xyz/xor/image/challenge/challenge
0x555555757000 0x555555778000 rw-p 21000 0 [heap]
0x7ffff7a0d000 0x7ffff7bcd000 r-xp 1c0000 0 /lib/x86_64-linux-gnu/libc-2.23.so
0x7ffff7bcd000 0x7ffff7dcd000 ---p 200000 1c0000 /lib/x86_64-linux-gnu/libc-2.23.so
0x7ffff7dcd000 0x7ffff7dd1000 r--p 4000 1c0000 /lib/x86_64-linux-gnu/libc-2.23.so
0x7ffff7dd1000 0x7ffff7dd3000 rw-p 2000 1c4000 /lib/x86_64-linux-gnu/libc-2.23.so
0x7ffff7dd3000 0x7ffff7dd7000 rw-p 4000 0
0x7ffff7dd7000 0x7ffff7dfd000 r-xp 26000 0 /lib/x86_64-linux-gnu/ld-2.23.so
0x7ffff7fdd000 0x7ffff7fe0000 rw-p 3000 0
0x7ffff7ff7000 0x7ffff7ffa000 r--p 3000 0 [vvar]
0x7ffff7ffa000 0x7ffff7ffc000 r-xp 2000 0 [vdso]
0x7ffff7ffc000 0x7ffff7ffd000 r--p 1000 25000 /lib/x86_64-linux-gnu/ld-2.23.so
0x7ffff7ffd000 0x7ffff7ffe000 rw-p 1000 26000 /lib/x86_64-linux-gnu/ld-2.23.so
0x7ffff7ffe000 0x7ffff7fff000 rw-p 1000 0
0x7ffffffde000 0x7ffffffff000 rw-p 21000 0 [stack]
0xffffffffff600000 0xffffffffff601000 r-xp 1000 0 [vsyscall]
특이하게 code영역에 w 권한을 줘서 쓰기가 가능하다. 일단 PIE가 걸려있어도 offset은 같기 때문에 code영역에 접근해 수정을 할 수 있다.
.bss:0000000000202200 ; _QWORD result[10]
.bss:0000000000202200 result dq 0Ah dup(?) ; DATA XREF: main+B0↑o
.bss:0000000000202200 ; main+C7↑o
.text:0000000000000AC3 mov edi, 1 ; status
.text:0000000000000AC8 call exit
이 부분을 수정할 것이다. 헥스로 보면 아래와 같다.
E8 63 FD FF FF
call의 opcode는 오프셋을 구해서 만들 수 있다.
E8 54 FF FF FF
저 위치에서 win을 호출하기 위한 opcode이다. 이를 0xAC8에 적어주면 된다.