int __cdecl main(int argc, const char **argv, const char **envp)
{
char *src; // ST08_8
__int64 buf; // [rsp+10h] [rbp-20h]
__int64 v6; // [rsp+18h] [rbp-18h]
unsigned __int64 v7; // [rsp+28h] [rbp-8h]
v7 = __readfsqword(0x28u);
setup();
buf = 0LL;
v6 = 0LL;
printf("Are you 18 years or older? [y/N]: ", argv);
*((_BYTE *)&buf + (signed int)((unsigned __int64)read(0, &buf, 0x10uLL) - 1)) = 0;
if ( (_BYTE)buf != 121 && (_BYTE)buf != 89 )
return 0;
src = (char *)malloc(0x84uLL);
printf("Name: ", &buf);
read(0, src, 0x80uLL);
strcpy(usr, src);
printf("Welcome ", src);
printf(qword_601160, usr);
return 0;
}
접속해보면, y/n, name 총 2개를 읽어온다.
flag 의 주소를 알고있으므로, 601080의 값을 읽어 올 수 있으면 풀릴것같다.
우린 601160 주소출력문을 이용해 601080값을 읽어와야 한다.
위 사진을 보면, usr + 0x80 = qword_601160인걸 알 수 있다.
0x80에 값을 넣을때 main문에선 read~>strcpy를 통해 값을 넣는다. 여기서 이용할 성질은 read는 입력이 끝난 후 null을 쓰지 않지만 strcpy는 null값을 쓴다. 따라서 만일 read에 0x80바이트를 다 넣을 경우, 마지막 1바이트가 null값으로 추가되고, 이 값은 qword_601160 값의 마지막 60부분에 침범하여 qword_601100으로 바뀌게 된다.
qword_601100은 printf() 의 매개변수로 쓰이기에, FSB방법을 사용할 수 있다.
FSB방법이란,
그냥 입력값에 인자를 넣어서 스택주소를 노출시키는 취약점을 이용한 것이고, 아직 완벽하게 이해하지 못했다.. 내일 fsb에 대해 더 자세하게 글을 올리겟다 :(
생각을 해보면,
처음 y를 입력받는 구문엔 16바이트를 read하고, 이름을 입력받을땐 80바이트를 받는다.
처음 입력받는 단계에서 우리가 가고싶은 주소, 0x601080을 입력하면 0x6010e0과 0x601160사이 어딘가에 주소가 들어갈 것이다. 0x601080엔 우리가 원하는 flag의 db가 들어가있고, 이 부분의 형식자를 %s로 뽑아주면 원하는 flag가 나올것이다.
여기서 원하는 0x601080의 위치를 찾았고, (9번째 %p) 이 부분을 %s로 바꿔주면,
원하는 flag가 나온다.
함수 참고~>
p32(value) : 32비트 리틀 엔디안 방식으로 패킹해주는 함수 (p32(value, endian='big')을 하면 빅 엔디안으로 패킹해준다)
p32(0x12345678) = \x78\x56\x34\x12
p64(value) : 64비트 리틀 엔디안 방식으로 패킹해주는 함수 (p64(value, endian='big')을 하면 빅 엔디안으로 패킹해준다)
p64(0x12345678) = \x00\x00\x00\x00\x78\x56\x34\x12
'pwnable > pwnable.xyz' 카테고리의 다른 글
[pwnable.xyz] two targets (0) | 2020.09.26 |
---|---|
[pwnable.xyz] note (0) | 2020.09.14 |
[pwnable.xyz] misalignment (0) | 2020.09.10 |
[pwnable.xyz] add (2) | 2020.09.09 |
[pwnable.xyz] sub (0) | 2020.09.07 |