ARM汇编之堆栈溢出实战分析(GDB)
引言
经过很长一段时间在azeria-labs进行的ARM基础汇编学习,学到了很多ARM汇编的基础知识、和简单的shellcode的编写,为了验证自己的学习成果,根据该网站提供的实例,做一次比较详细的逆向分析,和shellcode的实现,为自己的ARM入门学习巩固。
实例下载地址:git clone https://github.com/azeria-labs/ARM-challenges.git
调试环境:Linux raspberrypi 4.4.34+ #3 Thu Dec 1 14:44:23 IST 2016 armv6l GNU/Linux+GNU gdb (Raspbian 7.7.1+dfsg-5+rpi1) 7.7.1(这些都是按照网站教程安装的如果自己有ARM架构的操作系统也是可以的)
stack0
第一步,我们先看看文件的信息file stack0,从返回信息可以看出该程序是一个32位可执行程序,从最后的not stripped可以看出这个程序的符号信息,具体有关stripped详细介绍可以百度
stack0: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-armhf.so.3, for GNU/Linux 2.6.32, BuildID[sha1]=1171fa6db1d5176af44d6d462427f8d244bd82c8, not stripped
下面我们给他执行权限chmod +x stack0,然后执行它,会发现需要你的输入,表明这里使用了gets、scanf之类的输入方法,这些方法存在的地方就有溢出的风险,我们尝试构造一长一短的字符串,来测试一下。
短的字符串输出的让你重试的字样。
长的字符串,明显可以看出我们输入的值更改了变量导致,并且覆盖了返回地址,导致抛出Segmentation fault(访问了不可访问的内存,这个内存要么是不存在的,要么是受系统保护的)异常
分析出它存在溢出漏洞,现在我们就需要进入他的内部世界,彻底的洞悉它
首先我们需要找到他的入口函数,因为他没有删除符号数据,我们直接执行nm stack0,可以看到入口点、调用的库函数等信息,很明显入口点应该是main函数,我们来gdb走一波
U abort@@GLIBC_2.4
00020684 B __bss_end__
00020684 B _bss_end__
00020680 B __bss_start
00020680 B __bss_start__
00010360 t call_weak_fn
00020680 b completed.9004
00020678 D __data_start
00020678 W data_start
00010384 t deregister_tm_clones
000103ec t __do_global_dtors_aux
00020564 t __do_global_dtors_aux_fini_array_entry
0002067c D __dso_handle
0002056c d _DYNAMIC
00020680 D _edata
00020684 B _end
00020684 B __end__
00010510 T _fini
00010414 t frame_dummy
00020560 t __frame_dummy_init_array_entry
0001055c r __FRAME_END__
U gets@@GLIBC_2.4
00020654 d _GLOBAL_OFFSET_TABLE_
w __gmon_start__
000102c8 T _init
00020564 t __init_array_end
00020560 t __init_array_start
00010518 R _IO_stdin_used
w _ITM_deregisterTMCloneTable
w _ITM_registerTMCloneTable
00020568 d __JCR_END__
00020568 d __JCR_LIST__
w _Jv_RegisterClasses
0001050c T __libc_csu_fini
000104a8 T __libc_csu_init
U __libc_start_main@@GLIBC_2.4
0001044c T main
U puts@@GLIBC_2.4
000103b4 t register_tm_clones
00010324 T _start
00020680 D __TMC_END__
gef>disas stack0,我们可以看见得到main函数的反汇编代码,但是有一点不爽的是一些库函数API名称没有显示出来,这里提供两种解决思路:
升级gdb版本(百度、google找教程,我升级到8.2版本是可以显示的。这里有点奇怪的是,我的版本已经很高了,但是对这个二进制文件还是不能识别库函数并显示并且stripped前后都显示不了,但是对于有些二进制文件它又可以显示,如果有大佬知道,希望在评论里帮助解惑一下,thanks)
objdump 了解一下,这里我主要用的是objdump
Dump of assembler code for function main:
0x0001044c 0>: push {r11, lr}
0x00010450 4>: add r11, sp, #4
0x00010454 8>: sub sp, sp, #80 ; 0x50
0x00010458 12>: str r0, [r11, #-80] ; 0x50
0x0001045c 16>: str r1, [r11, #-84] ; 0x54
0x00010460 20>: mov r3, #0
0x00010464 24>: str r3, [r11, #-8]
0x00010468 28>: sub r3, r11, #72 ; 0x48
0x0001046c 32>: mov r0, r3
0x00010470 36>: bl 0x102e8
引言
经过很长一段时间在azeria-labs进行的ARM基础汇编学习,学到了很多ARM汇编的基础知识、和简单的shellcode的编写,为了验证自己的学习成果,根据该网站提供的实例,做一次比较详细的逆向分析,和shellcode的实现,为自己的ARM入门学习巩固。
实例下载地址:git clone https://github.com/azeria-labs/ARM-challenges.git
调试环境:Linux raspberrypi 4.4.34+ #3 Thu Dec 1 14:44:23 IST 2016 armv6l GNU/Linux+GNU gdb (Raspbian 7.7.1+dfsg-5+rpi1) 7.7.1(这些都是按照网站教程安装的如果自己有ARM架构的操作系统也是可以的)
stack0
第一步,我们先看看文件的信息file stack0,从返回信息可以看出该程序是一个32位可执行程序,从最后的not stripped可以看出这个程序的符号信息,具体有关stripped详细介绍可以百度 www.wnhack.com
stack0: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-armhf.so.3, for GNU/Linux 2.6.32, BuildID[sha1]=1171fa6db1d5176af44d6d462427f8d244bd82c8, not stripped
下面我们给他执行权限chmod +x stack0,然后执行它,会发现需要你的输入,表明这里使用了gets、scanf之类的输入方法,这些方法存在的地方就有溢出的风险,我们尝试构造一长一短的字符串,来测试一下。
短的字符串输出的让你重试的字样。
长的字符串,明显可以看出我们输入的值更改了变量导致,并且覆盖了返回地址,导致抛出Segmentation fault(访问了不可访问的内存,这个内存要么是不存在的,要么是受系统保护的)异常
分析出它存在溢出漏洞,现在我们就需要进入他的内部世界,彻底的洞悉它
首先我们需要找到他的入口函数,因为他没有删除符号数据,我们直接执行nm stack0,可以看到入口点、调用的库函数等信息,很明显入口点应该是main函数,我们来gdb走一波 copyright 无奈人生
U abort@@GLIBC_2.4
00020684 B __bss_end__
00020684 B _bss_end__
00020680 B __bss_start
00020680 B __bss_start__
00010360 t call_weak_fn
00020680 b completed.9004
00020678 D __data_start
00020678 W data_start
00010384 t deregister_tm_clones
000103ec t __do_global_dtors_aux
00020564 t __do_global_dtors_aux_fini_array_entry
0002067c D __dso_handle
0002056c d _DYNAMIC
00020680 D _edata
00020684 B _end
00020684 B __end__
00010510 T _fini
00010414 t frame_dummy
00020560 t __frame_dummy_init_array_entry
0001055c r __FRAME_END__
U gets@@GLIBC_2.4
00020654 d _GLOBAL_OFFSET_TABLE_
w __gmon_start__
000102c8 T _init
00020564 t __init_array_end
00020560 t __init_array_start
00010518 R _IO_stdin_used
w _ITM_deregisterTMCloneTable 内容来自无奈安全网
w _ITM_registerTMCloneTable
00020568 d __JCR_END__
00020568 d __JCR_LIST__
w _Jv_RegisterClasses
0001050c T __libc_csu_fini
000104a8 T __libc_csu_init
U __libc_start_main@@GLIBC_2.4
0001044c T main
U puts@@GLIBC_2.4
000103b4 t register_tm_clones
00010324 T _start
00020680 D __TMC_END__
gef>disas stack0,我们可以看见得到main函数的反汇编代码,但是有一点不爽的是一些库函数API名称没有显示出来,这里提供两种解决思路:
升级gdb版本(百度、google找教程,我升级到8.2版本是可以显示的。这里有点奇怪的是,我的版本已经很高了,但是对这个二进制文件还是不能识别库函数并显示并且stripped前后都显示不了,但是对于有些二进制文件它又可以显示,如果有大佬知道,希望在评论里帮助解惑一下,thanks)
objdump 了解一下,这里我主要用的是objdump
Dump of assembler code for function main: 本文来自无奈人生安全网
0x0001044c 0>: push {r11, lr}
0x00010450 4>: add r11, sp, #4
0x00010454 8>: sub sp, sp, #80 ; 0x50
0x00010458 12>: str r0, [r11, #-80] ; 0x50
0x0001045c 16>: str r1, [r11, #-84] ; 0x54
0x00010460 20>: mov r3, #0
0x00010464 24>: str r3, [r11, #-8]
0x00010468 28>: sub r3, r11, #72 ; 0x48
0x0001046c 32>: mov r0, r3
0x00010470 36>: bl 0x102e8
本文来自无奈人生安全网
无奈人生安全网