arm_android反汇编工作记录

这几天由于支持ipjone的需要,做了arm平台上的反汇编工作,由于汇编的东西较为复杂,所以需要形成文档,以备查阅。

首先,使用的反编译工具是ndk提供的toolchains里的交叉编译工具gcc。我们选取目标平台是arm的arm-linux-androideabi-4.7,工具路径是%ANDROID_NDK%\toolchains\arm-linux-androideabi-4.7\prebuilt\windows\arm-linux-androideabi\bin,里面有编译用的gcc和反编译用的objdump,我们就使用这个objdump进行下一步的工作。

在windows系统中,需要装一下linux环境cygwin。把路径cd到/home/bin下面,然后把前面找到的那个objdump.exe改个名字放到bin目录下面,我改成objdump_arm.exe用来使用。然后找到我们的android工程下面的jni文件夹,就是将c源代码编译成.o库的地方,生成的obj文件在obj文件夹里,各种找后找到.c文件对应的.o文件,将其copy到cygwin的bin文件夹下,用来做反编译。我这里用的是test.o。

然后就可以开始反编译了。往cygwin里面敲一个objdump_arm.exe,就可以看到帮助信息,如下:

$ objdump_arm.exe
Usage: C:\cygwin\bin\objdump_arm.exe <option(s)> <file(s)>
 Display information from object <file(s)>.
 At least one of the following switches must be given:
  -a, --archive-headers    Display archive header information
  -f, --file-headers       Display the contents of the overall file header
  -p, --private-headers    Display object format specific file header contents
  -P, --private=OPT,OPT... Display object format specific contents
  -h, --[section-]headers  Display the contents of the section headers
  -x, --all-headers        Display the contents of all headers
  -d, --disassemble        Display assembler contents of executable sections
  -D, --disassemble-all    Display assembler contents of all sections
  -S, --source             Intermix source code with disassembly
  -s, --full-contents      Display the full contents of all sections requested
  -g, --debugging          Display debug information in object file
  -e, --debugging-tags     Display debug information using ctags style
  -G, --stabs              Display (in raw form) any STABS info in the file
  -W[lLiaprmfFsoRt] or
  --dwarf[=rawline,=decodedline,=info,=abbrev,=pubnames,=aranges,=macro,=frames,
          =frames-interp,=str,=loc,=Ranges,=pubtypes,
          =gdb_index,=trace_info,=trace_abbrev,=trace_aranges]
                           Display DWARF info in the file
  -t, --syms               Display the contents of the symbol table(s)
  -T, --dynamic-syms       Display the contents of the dynamic symbol table
  -r, --reloc              Display the relocation entries in the file
  -R, --dynamic-reloc      Display the dynamic relocation entries in the file
  @<file>                  Read options from <file>
  -v, --version            Display this program's version number
  -i, --info               List object formats and architectures supported
  -H, --help               Display this information
从上面这些中选取我们需要的即可,这次的工作中用到的主要有-d,--source和-W三个。

首先-d可以直接给出大片大片的反汇编结果,举个栗子:

objdump_arm.exe -d test.o结果如下:

Disassembly of section .text.neon_short:

00000000 <neon_short>:
   0:   e0610000        rsb     r0, r1, r0
   4:   e3a0c000        mov     ip, #0
   8:   e92d4030        push    {r4, r5, lr}
   c:   f2c00050        vmov.i32        q8, #0  ; 0x00000000
  10:   e1a03001        mov     r3, r1
  14:   e3a04078        mov     r4, #120        ; 0x78
  18:   f26021f0        vorr    q9, q8, q8
  1c:   f26061f0        vorr    q11, q8, q8
  20:   f26081f0        vorr    q12, q8, q8
  24:   e2835d0f        add     r5, r3, #960    ; 0x3c0
  28:   e2544001        subs    r4, r4, #1
  2c:   f463574f        vld1.16 {d21}, [r3]
  30:   f465a74f        vld1.16 {d26}, [r5]
  34:   e2835d1e        add     r5, r3, #1920   ; 0x780
  38:   f465b74f        vld1.16 {d27}, [r5]
  3c:   e2835d2d        add     r5, r3, #2880   ; 0xb40
  40:   f465c74f        vld1.16 {d28}, [r5]
  44:   e0835000        add     r5, r3, r0
  48:   e2833008        add     r3, r3, #8
  4c:   f465474f        vld1.16 {d20}, [r5]
  50:   f2d508a4        vmlal.s16       q8, d21, d20
  54:   f2da28a4        vmlal.s16       q9, d26, d20
  58:   f2db68a4        vmlal.s16       q11, d27, d20
  5c:   f2dc88a4        vmlal.s16       q12, d28, d20
  60:   1affffef        bne     24 <neon_short+0x24>
  64:   f26141b1        vorr    d20, d17, d17
  68:   e1a03002        mov     r3, r2
  6c:   e2800d0f        add     r0, r0, #960    ; 0x3c0
  70:   f2644bb0        vpadd.i32       d20, d20, d16
  74:   f26301b3        vorr    d16, d19, d19
  78:   f2644bb4        vpadd.i32       d20, d20, d20
  7c:   f2602bb2        vpadd.i32       d18, d16, d18
  80:   f26701b7        vorr    d16, d23, d23
  84:   f2606bb6        vpadd.i32       d22, d16, d22
  88:   ee144b90        vmov.32 r4, d20[0]
  8c:   f26901b9        vorr    d16, d25, d25
  90:   f2622bb2        vpadd.i32       d18, d18, d18
  94:   e7a3400c        str     r4, [r3, ip]!
  98:   f2608bb8        vpadd.i32       d24, d16, d24
  9c:   e2834a02        add     r4, r3, #8192   ; 0x2000
  a0:   f2666bb6        vpadd.i32       d22, d22, d22
  a4:   e28cc004        add     ip, ip, #4
  a8:   f2688bb8        vpadd.i32       d24, d24, d24
  ac:   f4c4280f        vst1.32 {d18[0]}, [r4]
  b0:   e35c0a02        cmp     ip, #8192       ; 0x2000
  b4:   e2834901        add     r4, r3, #16384  ; 0x4000
  b8:   e2833a06        add     r3, r3, #24576  ; 0x6000
  bc:   f4c4680f        vst1.32 {d22[0]}, [r4]
  c0:   f4c3880f        vst1.32 {d24[0]}, [r3]
  c4:   1affffd0        bne     c <neon_short+0xc>
  c8:   e8bd8030        pop     {r4, r5, pc}
直接把这个结果粘到编辑器里,修改一下,就可以使用了。

另外,--source选项可以得到和源代码对应的反汇编结果,在一定程度上能够帮助你稍微看懂一点汇编代码,但是作用并不是太大,而且看起来很乱。

还有就是-W选项,它可以查到一些变量和寄存器的对应关系,比方说我面对着一堆令人费解的汇编代码,想找到正确的寄存器把输入参数传进去,就可以使用-W选项碰碰运气,一旦使用了之后,会出现好大一片结果,在浩如烟海的字符里,可能就会找到你需要的变量名和寄存器的对应关系。我就是从里面找到的。三个输入参数分别对应于r0、r1和r2。

现在有了汇编代码,我们就只需要修改它就好了,还有就是最后的集成工作,怎么样把我们的汇编代码嵌入到C代码中运行。首先要找到函数的输入和输出,确定下来对应的寄存器,准备传参。

嵌入格式如下:

__asm__ __volatile__(
		"push    {r4, r5, lr}\n\t"
		
		"mov	 r0,	%[pWeight]\n\t"	
		"mov	 r1,	%[pValueIn]\n\t"		
		"mov	 r2,	%[pValueOut]\n\t"
		
		"rsb     r0, r1, r0\n\t"
		"mov     ip, #0\n\t"
		"1:vmov.i32        q8, #0\n\t"
		"mov     r3, r1\n\t"
		"mov     r4, #120\n\t"
		"vorr    q9, q8, q8\n\t"
		"vorr    q11, q8, q8\n\t"
		"vorr    q12, q8, q8\n\t"
		"2:add     r5, r3, #960\n\t"
		"subs    r4, r4, #1\n\t"
		"vld1.16 {d21}, [r3]\n\t"
		"vld1.16 {d26}, [r5]\n\t"
		"add     r5, r3, #1920\n\t"
		"vld1.16 {d27}, [r5]\n\t"
		"add     r5, r3, #2880\n\t"
		"vld1.16 {d28}, [r5]\n\t"
		"add     r5, r3, r0\n\t"
		"add     r3, r3, #8\n\t"
		"vld1.16 {d20}, [r5]\n\t"
		"vmlal.s16       q8, d21, d20\n\t"
		"vmlal.s16       q9, d26, d20\n\t"
		"vmlal.s16       q11, d27, d20\n\t"
		"vmlal.s16       q12, d28, d20\n\t"
		"bne     2b\n\t"
		"vorr    d20, d17, d17\n\t"
		"mov     r3, r2\n\t"
		"add     r0, r0, #960\n\t"
		"vpadd.i32       d20, d20, d16\n\t"
		"vorr    d16, d19, d19\n\t"
		"vpadd.i32       d20, d20, d20\n\t"
		"vpadd.i32       d18, d16, d18\n\t"
		"vorr    d16, d23, d23\n\t"
		"vpadd.i32       d22, d16, d22\n\t"
		"vmov.32 r4, d20[0]\n\t"
		"vorr    d16, d25, d25\n\t"
		"vpadd.i32       d18, d18, d18\n\t"
		"str     r4, [r3, ip]!\n\t"
		"vpadd.i32       d24, d16, d24\n\t"
		"add     r4, r3, #8192\n\t"
		"vpadd.i32       d22, d22, d22\n\t"
		"add     ip, ip, #4\n\t"
		"vpadd.i32       d24, d24, d24\n\t"
		"vst1.32 {d18[0]}, [r4]\n\t"
		"cmp     ip, #8192\n\t"
		"add     r4, r3, #16384\n\t"
		"add     r3, r3, #24576\n\t"
		"vst1.32 {d22[0]}, [r4]\n\t"
		"vst1.32 {d24[0]}, [r3]\n\t"
		"bne     1b\n\t"
		"pop     {r4, r5, pc}\n\t"
		
		:
		:[pWeight] "r" (weight), [pValueIn] "r" (value_in), [pValueOut] "r" (value_out)
		);
从这个可以看出,前后各加了一坨代码,用来声明和传参。后面带冒号那两行是输入输出的声明,第一行表示输出,没有就空着,有的话需要写成:

		:[pValueOut] "=r" (value_out)

注意,和输入的写法不同,需要加一个等号。

然后前面的赋值没什么可说的,只要找准寄存器就好了。

现在汇编代码就可以嵌入到源代码里去编译运行了,但是没准还是会遇到编译不通过的问题。比方说我就遇到了。因为有一个指令叫strhle和strhgt,明明是反汇编出来的,却打死都编译不过,直接报error,说那是“Bad Instrution”,令我百思不得其解。后来各种查,改成strleh和strgth才好使了。实在搞不懂为什么自己反汇编出来的代码自己都编不过,弄不懂。

在这个工作当中,学到了一些东西,比如cmp指令,用来做if跳转分支,cmp后面会接一些条件判断指令,le和gt表示<=和>还有两个我记不清了,反正都挺无聊的。前面的那个错误也是在cmp后面做判断用的,str指令用来保存数据到内存,h表示是半字,le和gt表示大于还是小于,所以是顺序没排对,而不是两条不同的指令。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值