欢迎来到 嗅灵易学

零基础也能上手的脚本技术课,一对一答疑带你入门

[原创]Arm opcode hook

[原创]Arm opcode hook

/**************************************
/* 
/* 博客:http://cnblogs.com/bjblcracked
/* 
/**************************************

只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
因工作需要,最近一直在研究arm.
看到论坛也有不少arm的破解文章,于是自己也写了个"CM",把玩一下.
这里就不讲破解了,重点讲ARM HOOK.

所需平台1:ubuntu x86 (build arm)
所需平台2:win7 x86 (debug arm)
所需平台3:android手机一部(root)
所需工具1:ida(analysis)
所需工具2:pscp(upload,download file)
所需工具3:putty(connect ubuntu)
所需工具4:gcc(build arm)

首先用标准C写个简单的cm.


#include <stdio.h>

int IsAdd(int* pNumOne, int* pNumTwo)

{

  return *pNumOne + *pNumTwo;

}

int main()

{

  int nNumOne = 0;

  int nNumTwo = 0;

  int nNumResult = 0;

  printf("hi arm code.\r\n");

  printf("Please Input a Name:");

  scanf("%d", &nNumOne);

  printf("\r\n");

  printf("Please Input a Password:");

  scanf("%d", &nNumTwo);

  printf("\r\n");

  nNumResult = IsAdd(&nNumOne, &nNumTwo);

  printf("%d + %d = %d\r\n", nNumOne, nNumTwo, nNumResult);

  if(nNumResult != 2013)

  {

     printf("error\r\n"); 

  }

  else

  {

     printf("success\r\n");

  }

  return 1;

}


测试代码,写的不严谨.

1). 连接ubuntu.


login as: root
root@192.168.83.150's password:
Welcome to Ubuntu 12.04.2 LTS (GNU/Linux 3.5.0-23-generic x86_64)
 * Documentation:  https://help.ubuntu.com/
258 packages can be updated.
89 updates are security updates.
Last login: Thu Aug 29 11:05:46 2013 from john-pc.local
root@i-G31MXP-K-T1:~# whoami
root
root@i-G31MXP-K-T1:~#

用putty.exe连接上ubuntu了,我们再把我们的源码上传上来.

2). upload cm src.


D:\Me\Company>pscp.exe -l root -pw password D:\Me\Company\armhook.c root@192.168.83.150:/root/zs/
armhook.c                      | 0 kB |   0.6 kB/s | ETA: 00:00:00 | 100%
D:\Me\Company>

这里我们用pscp.exe上传源码.

3). build arm.


root@i-G31MXP-K-T1:~/zs# arm-none-linux-gnueabi-gcc -static armhook.c -o armhook
root@i-G31MXP-K-T1:~/zs# ls -l
total 640
-rwxr-xr-x 1 root root 649852 Aug 29 16:16 armhook
-rw-r--r-- 1 root root    623 Aug 29 16:11 armhook.c
root@i-G31MXP-K-T1:~/zs#

用gcc编译arm.这里一定要静态编译,要不然在你的android手机上是运行不了的.

4). 下载bin到pc端


D:\Me\Company>pscp.exe -l root -pw password root@192.168.83.150:/root/zs/armhook D:\Me\Company
armhook                        | 634 kB | 634.6 kB/s | ETA: 00:00:00 | 100%

再用pscp.exe下载回来.
bin下载到PC上时,我们就可以用IDA调试了,我们先发到手机里面,运行一下,看看效果.

5). bin发送到手机端.


C:\Users\john\Desktop\Tools>adb push d:/me/company/armhook /data/local/tmp/
2173 KB/s (649852 bytes in 0.292s)
C:\Users\john\Desktop\Tools>adb shell
shell@android:/ $ su
su
shell@android:/ # pwd
pwd
/
shell@android:/ # cd data/local/tmp
cd data/local/tmp
shell@android:/data/local/tmp # ls
ls
armhook
shell@android:/data/local/tmp # ./armhook
./armhook
sh: ./armhook: can't execute: Permission denied
126|shell@android:/data/local/tmp # chmod 777 armhook
chmod 777 armhook
shell@android:/data/local/tmp # ./armhook
./armhook
hi arm code.
Please Input a Name:2000
2000
Please Input a Password:12
12
2000 + 12 = 2012
error
1|shell@android:/data/local/tmp # ./armhook
./armhook
hi arm code.
Please Input a Name:2000
2000
Please Input a Password:13
13
2000 + 13 = 2013
success
1|shell@android:/data/local/tmp #


6). 静态调试分析.

手机上测试完了,下面我们就用IDA来看看程序.

.text:00008204             ; =============== S U B R O U T I N E =======================================

.text:00008204             ; Attributes: noreturn bp-based frame

.text:00008204                             EXPORT main

.text:00008204             main                                    ; DATA XREF: _start+20o

.text:00008204                                                     ; .text:off_8154o

.text:00008204             var_10          = -0x10

.text:00008204             var_C           = -0xC

.text:00008204             var_8           = -8

.text:00008204 00 48 2D E9                 STMFD   SP!, {R11,LR}   ; Store Block to Memory

.text:00008208 04 B0 8D E2                 ADD     R11, SP, #4     ; Rd = Op1 + Op2

.text:0000820C 10 D0 4D E2                 SUB     SP, SP, #0x10   ; Rd = Op1 - Op2

.text:00008210 00 30 A0 E3                 MOV     R3, #0          ; Rd = Op2

.text:00008214 0C 30 0B E5                 STR     R3, [R11,#var_C] ; Store to Memory

.text:00008218 00 30 A0 E3                 MOV     R3, #0          ; Rd = Op2

.text:0000821C 10 30 0B E5                 STR     R3, [R11,#var_10] ; Store to Memory

.text:00008220 00 30 A0 E3                 MOV     R3, #0          ; Rd = Op2

.text:00008224 08 30 0B E5                 STR     R3, [R11,#var_8] ; Store to Memory

.text:00008228 BC 00 9F E5                 LDR     R0, =aHiArmCode_ ; "hi arm code.\r"

.text:0000822C 19 0B 00 EB                 BL      puts            ; Branch with Link

.text:00008230 B8 30 9F E5                 LDR     R3, =aPleaseInputANa ; "Please Input a Name:"

.text:00008234 03 00 A0 E1                 MOV     R0, R3          ; Rd = Op2

.text:00008238 80 0A 00 EB                 BL      printf          ; Branch with Link

.text:0000823C B0 20 9F E5                 LDR     R2, =aD         ; "%d"

.text:00008240 0C 30 4B E2                 SUB     R3, R11, #-var_C ; Rd = Op1 - Op2

.text:00008244 02 00 A0 E1                 MOV     R0, R2          ; Rd = Op2

.text:00008248 03 10 A0 E1                 MOV     R1, R3          ; Rd = Op2

.text:0000824C 8A 0A 00 EB                 BL      __isoc99_scanf  ; Branch with Link

.text:00008250 A0 00 9F E5                 LDR     R0, =asc_6FE98  ; "\r"

.text:00008254 0F 0B 00 EB                 BL      puts            ; Branch with Link

.text:00008258 9C 30 9F E5                 LDR     R3, =aPleaseInputAPa ; "Please Input a Password:"

.text:0000825C 03 00 A0 E1                 MOV     R0, R3          ; Rd = Op2

.text:00008260 76 0A 00 EB                 BL      printf          ; Branch with Link

.text:00008264 88 20 9F E5                 LDR     R2, =aD         ; "%d"

.text:00008268 10 30 4B E2                 SUB     R3, R11, #-var_10 ; Rd = Op1 - Op2

.text:0000826C 02 00 A0 E1                 MOV     R0, R2          ; Rd = Op2

.text:00008270 03 10 A0 E1                 MOV     R1, R3          ; Rd = Op2

.text:00008274 80 0A 00 EB                 BL      __isoc99_scanf  ; Branch with Link

.text:00008278 78 00 9F E5                 LDR     R0, =asc_6FE98  ; "\r"

.text:0000827C 05 0B 00 EB                 BL      puts            ; Branch with Link

.text:00008280 0C 20 4B E2                 SUB     R2, R11, #-var_C ; Rd = Op1 - Op2

.text:00008284 10 30 4B E2                 SUB     R3, R11, #-var_10 ; Rd = Op1 - Op2

.text:00008288 02 00 A0 E1                 MOV     R0, R2          ; Rd = Op2

.text:0000828C 03 10 A0 E1                 MOV     R1, R3          ; Rd = Op2

.text:00008290 CD FF FF EB                 BL      IsAdd           ; Branch with Link

.text:00008294 08 00 0B E5                 STR     R0, [R11,#var_8] ; Store to Memory

.text:00008298 60 10 9F E5                 LDR     R1, =aDDD       ; "%d + %d = %d\r\n"

.text:0000829C 0C 20 1B E5                 LDR     R2, [R11,#var_C] ; Load from Memory

.text:000082A0 10 30 1B E5                 LDR     R3, [R11,#var_10] ; Load from Memory

.text:000082A4 01 00 A0 E1                 MOV     R0, R1          ; Rd = Op2

.text:000082A8 02 10 A0 E1                 MOV     R1, R2          ; Rd = Op2

.text:000082AC 03 20 A0 E1                 MOV     R2, R3          ; Rd = Op2

.text:000082B0 08 30 1B E5                 LDR     R3, [R11,#var_8] ; Load from Memory

.text:000082B4 61 0A 00 EB                 BL      printf          ; Branch with Link

.text:000082B8 08 20 1B E5                 LDR     R2, [R11,#var_8] ; Load from Memory

.text:000082BC 40 30 9F E5                 LDR     R3, =0x7DD      ; Load from Memory

.text:000082C0 03 00 52 E1                 CMP     R2, R3          ; Set cond. codes on Op1 - Op2

.text:000082C4 02 00 00 0A                 BEQ     loc_82D4        ; Branch

.text:000082C8 38 00 9F E5                 LDR     R0, =aError     ; "error\r"

.text:000082CC F1 0A 00 EB                 BL      puts            ; Branch with Link

.text:000082D0 01 00 00 EA                 B       loc_82DC        ; Branch

.text:000082D4             loc_82D4                                ; CODE XREF: main+C0j

.text:000082D4 30 00 9F E5                 LDR     R0, =aSuccess   ; "success\r"

.text:000082D8 EE 0A 00 EB                 BL      puts            ; Branch with Link

.text:000082DC             loc_82DC                                ; CODE XREF: main+CCj

.text:000082DC 01 30 A0 E3                 MOV     R3, #1          ; Rd = Op2

.text:000082E0 03 00 A0 E1                 MOV     R0, R3          ; Rd = Op2

.text:000082E4 04 D0 4B E2                 SUB     SP, R11, #4     ; Rd = Op1 - Op2

.text:000082E8 00 88 BD E8                 LDMFD   SP!, {R11,PC}   ; Load Block from Memory

.text:000082E8             ; End of function main

.text:000082EC 6C FE 06 00 off_82EC        DCD aHiArmCode_         ; DATA XREF: main+24r

.text:000082EC                                                     ; "hi arm code.\r"

.text:000082F0 7C FE 06 00 off_82F0        DCD aPleaseInputANa     ; DATA XREF: main+2Cr

.text:000082F0                                                     ; "Please Input a Name:"

.text:000082F4 94 FE 06 00 off_82F4        DCD aD                  ; DATA XREF: main+38r

.text:000082F4                                                     ; main+60r

.text:000082F4                                                     ; "%d"

.text:000082F8 98 FE 06 00 off_82F8        DCD asc_6FE98           ; DATA XREF: main+4Cr

.text:000082F8                                                     ; main+74r

.text:000082F8                                                     ; "\r"

.text:000082FC 9C FE 06 00 off_82FC        DCD aPleaseInputAPa     ; DATA XREF: main+54r

.text:000082FC                                                     ; "Please Input a Password:"

.text:00008300 B8 FE 06 00 off_8300        DCD aDDD                ; DATA XREF: main+94r

.text:00008300                                                     ; "%d + %d = %d\r\n"

.text:00008304 DD 07 00 00 dword_8304      DCD 0x7DD               ; DATA XREF: main+B8r

.text:00008308 C8 FE 06 00 off_8308        DCD aError              ; DATA XREF: main+C4r

.text:00008308                                                     ; "error\r"

.text:0000830C D0 FE 06 00 off_830C        DCD aSuccess            ; DATA XREF: main:loc_82D4r

.text:0000830C                                                     ; "success\r"

.text:00008310             ; =============== S U B R O U T I N E =======================================


程序很简单,看反汇编代码,一眼就能定位到magic jump.

.text:000082B8             ; ---------------------------------------------------------------------------

.text:000082B8 08 20 1B E5                 LDR     R2, [R11,#var_8] ; Load from Memory

.text:000082BC 40 30 9F E5                 LDR     R3, =0x7DD      ; Load from Memory

.text:000082C0 03 00 52 E1                 CMP     R2, R3          ; Set cond. codes on Op1 - Op2

.text:000082C4 02 00 00 0A                 BEQ     loc_82D4        ; Branch

.text:000082C8 38 00 9F E5                 LDR     R0, =aError     ; "error\r"

.text:000082CC F1 0A 00 EB                 BL      puts            ; Branch with Link

.text:000082D0 01 00 00 EA                 B       loc_82DC        ; Branch

.text:000082D4             ; ---------------------------------------------------------------------------


我们只要把beq改成 bne就可以了.
或者直接改成 B   loc_82D4 .这样都可以实现爆破.
文本重点是讲HOOK,就不多说破解过程了.
CM写的很简洁,就一个isadd函数,那么我们就来尝试HOOK IsAdd函数.

.text:000081CC                             EXPORT IsAdd

.text:000081CC             IsAdd                                   ; CODE XREF: main+8Cp

.text:000081CC 04 B0 2D E5                 STR     R11, [SP,#-4]!  ; Store to Memory

.text:000081D0 00 B0 8D E2                 ADD     R11, SP, #0     ; Rd = Op1 + Op2

.text:000081D4 0C D0 4D E2                 SUB     SP, SP, #0xC    ; Rd = Op1 - Op2

.text:000081D8 08 00 0B E5                 STR     R0, [R11,#-8]   ; Store to Memory

.text:000081DC 0C 10 0B E5                 STR     R1, [R11,#-0xC] ; Store to Memory

.text:000081E0 08 30 1B E5                 LDR     R3, [R11,#-8]   ; Load from Memory

.text:000081E4 00 20 93 E5                 LDR     R2, [R3]        ; Load from Memory

.text:000081E8 0C 30 1B E5                 LDR     R3, [R11,#-0xC] ; Load from Memory

.text:000081EC 00 30 93 E5                 LDR     R3, [R3]        ; Load from Memory

.text:000081F0 03 30 82 E0                 ADD     R3, R2, R3      ; Rd = Op1 + Op2

.text:000081F4 03 00 A0 E1                 MOV     R0, R3          ; Rd = Op2

.text:000081F8 00 D0 8B E2                 MOV     SP, R11         ; Rd = Op2

.text:000081FC 04 B0 9D E4                 LDR     R11, [SP],#4    ; Load from Memory

.text:00008200 1E FF 2F E1                 BX      LR              ; Branch to/from Thumb mode


其HOOK思路和x86下是一样的.
不同的是更"繁琐"些,而且"jmp"计算公式也略有不同.
在arm中,没有jmp指令,而是只有bcc指令(类似jcc).
之所以说HOOK繁琐,主要是对arm指令集不了解,所以HOOK起来感觉更繁琐些,其实都一样的,甚至更简单些 :)
具体的bcc,大家可以看我博客收集的一篇文章.
传送门:
ARM Cortex M3指令集

在arm中hook我们需要用到 bl 这个转移指令 .
其效果和x86中的 call 有点类似.
下面来说说arm bcc的公式.(自己多次尝试总结的,如果有不对的地方希望大家能指点一下.)

计算opcode:
(dst - src) / 4 - 2 = opcode
计算dst:
src + (opcode + 2) * 4 = dst

 
不明看例:)

ROM:9D039D3C 108 1C 00 00 1A                 BNE     loc_9D039DB4    ; Branch

(9D039DB4 - 9D039D3C) / 4 - 2 = 1c

9D039D3C + (1c + 2) * 4 = 9D039DB4

ROM:9D039D90 108 07 00 00 EA                 B       loc_9D039DB4    ; Branch

(9D039DB4 - 9D039D90) / 4 - 2 = 7

9D039D90 + (7 + 2) * 4 = 9D039DB4


下面开始HOOK,我们需要先把入口代码和地址记下来.

000081CC 04 B0 2D E5     STR     R11, [SP,#-4+var_s0]! ; Store to Memory


要HOOK地址:000081CC
OPCODE:04 B0 2D E5
下面我们再程序中找段空数据地址.

.rodata:00072320 02 02 02 02                 ANDEQ   R0, R2, #0x20000000 ; Rd = Op1 & Op2

.rodata:00072324 02 02 02 02                 ANDEQ   R0, R2, #0x20000000 ; Rd = Op1 & Op2

.rodata:00072328 02 02 02 02                 ANDEQ   R0, R2, #0x20000000 ; Rd = Op1 & Op2

.rodata:0007232C 02 02 02 02                 ANDEQ   R0, R2, #0x20000000 ; Rd = Op1 & Op2

.rodata:00072330 02 02 02 02                 ANDEQ   R0, R2, #0x20000000 ; Rd = Op1 & Op2

.rodata:00072334 02 02 02 02                 ANDEQ   R0, R2, #0x20000000 ; Rd = Op1 & Op2

.rodata:00072338 02 02 02 02                 ANDEQ   R0, R2, #0x20000000 ; Rd = Op1 & Op2


我找的这个没用的数据地址.来写我们的HOOK代码.
我们套用opcode计算公式.

(dst - src) / 4 - 2 =opcode
(00072320 - 000081CC) / 4 - 2 = 0x01A853

我们计算出opcode等于0x1A852 
bl 指令对应的指令是 0xeb
那么合起来就是,  53 a8 01 eb (arm很有意思,所有的指令都是4字节对齐的.)
修改,我们就直接用IDA的插件. 组合热键是 alt+e+p+b .
IDA的这个插件对ARM支持不是很友好,不能直接编写汇编代码.
因此我们只能按字节来修改了.(字节之间都要有空格,不区分大小写.)
打开后,我们在前四个字节,输入 53 a8 01 eb 然后确定就行了.
改了后如下效果.

.text:000081CC             IsAdd                                   ; CODE XREF: main+8Cp
.text:000081CC 53 A8 01 EB                 BL      loc_72320       ; Branch with Link
.text:000081D0 00 B0 8D E2                 ADD     R11, SP, #0     ; Rd = Op1 + Op2
.text:000081D4 0C D0 4D E2                 SUB     SP, SP, #0xC    ; Rd = Op1 - Op2
.text:000081D8 08 00 0B E5                 STR     R0, [R11,#-8]   ; Store to Memory
.text:000081DC 0C 10 0B E5                 STR     R1, [R11,#-0xC] ; Store to Memory
.text:000081E0 08 30 1B E5                 LDR     R3, [R11,#-8]   ; Load from Memory
.text:000081E4 00 20 93 E5                 LDR     R2, [R3]        ; Load from Memory
.text:000081E8 0C 30 1B E5                 LDR     R3, [R11,#-0xC] ; Load from Memory
.text:000081EC 00 30 93 E5                 LDR     R3, [R3]        ; Load from Memory
.text:000081F0 03 30 82 E0                 ADD     R3, R2, R3      ; Rd = Op1 + Op2
.text:000081F4 03 00 A0 E1                 MOV     R0, R3          ; Rd = Op2
.text:000081F8 00 D0 8B E2                 MOV     SP, R11         ; Rd = Op2
.text:000081FC 04 B0 9D E4                 LDR     R11, [SP],#4    ; Load from Memory
.text:00008200 1E FF 2F E1                 BX      LR              ; Branch to/from Thumb mode
[/CODE]
注意看81cc处的指令已经被我们改了.
现在我们要到 loc_72310 这里, 
我们就来打印一个"hi arm hook" 吧.
打印的话,我们要调用 puts 函数,
我们来看一下函数地址.

.text:0000AE98             puts                                    ; CODE XREF: main+28p

.text:0000AE98                                                     ; main+50p ...

.text:0000AE98 F0 47 2D E9                 STMFD   SP!, {R4-R10,LR} ; Alternative name is '_IO_puts'

.text:0000AE9C 00 90 A0 E1                 MOV     R9, R0          ; Rd = Op2

.text:0000AEA0 1E 27 00 EB                 BL      strlen          ; Branch with Link

.text:0000AEA4 3C 72 9F E5                 LDR     R7, =stdout     ; Load from Memory

.text:0000AEA8 00 60 97 E5                 LDR     R6, [R7]        ; Load from Memory

.text:0000AEAC 00 40 96 E5                 LDR     R4, [R6]        ; Load from Memory

.text:0000AEB0 02 49 14 E2                 ANDS    R4, R4, #0x8000 ; Rd = Op1 & Op2

.text:0000AEB4 00 A0 A0 E1                 MOV     R10, R0         ; Rd = Op2

.text:0000AEB8 59 00 00 1A                 BNE     loc_B024        ; Branch

.text:0000AEBC 48 50 96 E5                 LDR     R5, [R6,#0x48]  ; Load from Memory

.text:0000AEC0 B2 FD FF EB                 BL      __aeabi_read_tp ; Branch with Link

.text:0000AEC4 08 30 95 E5                 LDR     R3, [R5,#8]     ; Load from Memory

.text:0000AEC8 13 8D 40 E2                 SUB     R8, R0, #0x4C0  ; Rd = Op1 - Op2

.text:0000AECC 08 00 53 E1                 CMP     R3, R8          ; Set cond. codes on Op1 - Op2

.text:0000AED0 0E 00 00 0A                 BEQ     loc_AF10        ; Branch

.text:0000AED4 01 10 A0 E3                 MOV     R1, #1          ; Rd = Op2

.text:0000AED8 05 20 A0 E1                 MOV     R2, R5          ; Rd = Op2

...

...


puts地址:0000AE98
函数原型:

int puts( const char *string );


就一个参数. arm的程序都有点类似delphi的_fastcall. 通过寄存器传参.
当参数超过四个后,就会通过栈来传参. 寄存器顺序是 r0 r1 r2 r3.
puts 就一个参数,我们只要把 "hi arm hook" 地址赋给 r0 即可.
传地址不能用 mov .要用类似 lea 的 ldr 指令.  opcode: 0x0000e59f
前面说了arm是四字节指令, 光 ldr 就占了 2个字节 3 和 4字节.
那么第2个字节表示的是 寄存器. 第一个字节 表示字符串的偏移.
因为arm的risc指令为单字指令,所以他的寻址只能是255.
我们在刚才找的空数据地址段下面写上 "hi arm hook" 

.rodata:00072320 02 02 02 02     ANDEQ   R0, R2, #0x20000000         ; Rd = Op1 & Op2

.rodata:00072324 02 02 02 02     ANDEQ   R0, R2, #0x20000000         ; Rd = Op1 & Op2

.rodata:00072328 02 02 02 02     ANDEQ   R0, R2, #0x20000000         ; Rd = Op1 & Op2

.rodata:0007232C 02 02 02 02     ANDEQ   R0, R2, #0x20000000         ; Rd = Op1 & Op2

.rodata:00072330 02 02 02 02     ANDEQ   R0, R2, #0x20000000         ; Rd = Op1 & Op2

.rodata:00072334 02 02 02 02     ANDEQ   R0, R2, #0x20000000         ; Rd = Op1 & Op2

.rodata:00072338 02 02 02 02     ANDEQ   R0, R2, #0x20000000         ; Rd = Op1 & Op2

.rodata:0007233C 02 0A 02 02     ANDEQ   R0, R2, #0x2000             ; Rd = Op1 & Op2

.rodata:00072340 02 02 05 02     ANDEQ   R0, R5, #0x20000000         ; Rd = Op1 & Op2

.rodata:00072344 0E 0F 02 02     ANDEQ   R0, R2, #0x38               ; Rd = Op1 & Op2

.rodata:00072348 02 02 02 02     ANDEQ   R0, R2, #0x20000000         ; Rd = Op1 & Op2

.rodata:0007234C 02 02 02 02     ANDEQ   R0, R2, #0x20000000         ; Rd = Op1 & Op2

.rodata:0007234C             ; ---------------------------------------------------------------------------

.rodata:00072350 68 69 20 61+aHiArmHook DCB "hi arm hook",0

.rodata:0007235C             ; ---------------------------------------------------------------------------

.rodata:0007235C 02 02 02 02     ANDEQ   R0, R2, #0x20000000         ; Rd = Op1 & Op2

.rodata:00072360 02 02 02 02     ANDEQ   R0, R2, #0x20000000         ; Rd = Op1 & Op2


在x86上,我们HOOK前要保存现场,在ARM中,也同样需要保护现场.
STMFD 指令是用来保存现场的,满递减堆栈
恢复的话,我们就用
LDMFD指令.满递减堆栈
因为我对arm指令集并不熟悉,x86上也没有发现有什么比较好的指令和汇编转换工具.
所以我也不知道代码对应的opcode是多少,也没有时间一个个去试.
所以我就直接找puts函数入口处的opcode
保存现场
F0 47 2D E9         STMFD   SP!, {R4-R10,LR}  // 将R4-R10 LR 入栈,满递减堆栈
恢复现场
F0 87 BD E8         LDMFD   SP!, {R4-R10,PC}  // 将R4-R10 LR 出栈,满递减堆栈
00072320处,我们填写 F0 47 2D E9 保存现场.
保护好现场后,我们就来实现我们要打印的内容.
00072324处,我们把这个字符串装进r0.

ldr 1字节换算公式:
dst - src - 8 = opcode

套进去后:
00072350 - 00072324 - 8 = 24
24 00 9f e5

.rodata:00072320 F0 47 2D E9         STMFD   SP!, {R4-R10,LR}        ; Store Block to Memory

.rodata:00072324 24 00 9F E5         LDR     R0, aHiArmHook          ; "hi arm hook"

.rodata:00072328 02 02 02 02         ANDEQ   R0, R2, #0x20000000     ; Rd = Op1 & Op2

.rodata:0007232C 02 02 02 02         ANDEQ   R0, R2, #0x20000000     ; Rd = Op1 & Op2

.rodata:00072330 02 02 02 02         ANDEQ   R0, R2, #0x20000000     ; Rd = Op1 & Op2

.rodata:00072334 02 02 02 02         ANDEQ   R0, R2, #0x20000000     ; Rd = Op1 & Op2

.rodata:00072338 02 02 02 02         ANDEQ   R0, R2, #0x20000000     ; Rd = Op1 & Op2

.rodata:0007233C 02 0A 02 02         ANDEQ   R0, R2, #0x2000         ; Rd = Op1 & Op2

.rodata:00072340 02 02 05 02         ANDEQ   R0, R5, #0x20000000     ; Rd = Op1 & Op2

.rodata:00072344 0E 0F 02 02         ANDEQ   R0, R2, #0x38           ; Rd = Op1 & Op2

.rodata:00072348 02 02 02 02         ANDEQ   R0, R2, #0x20000000     ; Rd = Op1 & Op2

.rodata:0007234C 02 02 02 02         ANDEQ   R0, R2, #0x20000000     ; Rd = Op1 & Op2

.rodata:0007234C             ; ---------------------------------------------------------------------------

.rodata:00072350 68 69 20 61+aHiArmHook DCB "hi arm hook",0          ; DATA XREF: .rodata:00072324r

.rodata:0007235C             ; ---------------------------------------------------------------------------

.rodata:0007235C 02 02 02 02         ANDEQ   R0, R2, #0x20000000     ; Rd = Op1 & Op2


下面我们就剩跳到puts了.
再来看一下公式.
(dst - src) / 4 - 2 =opcode
puts地址:0000AE98
(0000AE98 - 00072328) / 4 - 2 = FFFF FFFF FFFE 62DA
我们只要取三字节就行了,也就是  da62fe加上bl eb

.rodata:00072320             loc_72320                               ; CODE XREF: .text:IsAddp

.rodata:00072320 F0 47 2D E9         STMFD   SP!, {R4-R10,LR}        ; Store Block to Memory

.rodata:00072324 24 00 9F E5         LDR     R0, aHiArmHook          ; "hi arm hook"

.rodata:00072328 DA 62 FE EB         BL      puts                    ; Branch with Link

.rodata:0007232C 02 02 02 02         ANDEQ   R0, R2, #0x20000000     ; Rd = Op1 & Op2

.rodata:00072330 02 02 02 02         ANDEQ   R0, R2, #0x20000000     ; Rd = Op1 & Op2

.rodata:00072334 02 02 02 02         ANDEQ   R0, R2, #0x20000000     ; Rd = Op1 & Op2

.rodata:00072338 02 02 02 02         ANDEQ   R0, R2, #0x20000000     ; Rd = Op1 & Op2

.rodata:0007233C 02 0A 02 02         ANDEQ   R0, R2, #0x2000         ; Rd = Op1 & Op2

.rodata:00072340 02 02 05 02         ANDEQ   R0, R5, #0x20000000     ; Rd = Op1 & Op2

.rodata:00072344 0E 0F 02 02         ANDEQ   R0, R2, #0x38           ; Rd = Op1 & Op2

.rodata:00072348 02 02 02 02         ANDEQ   R0, R2, #0x20000000     ; Rd = Op1 & Op2

.rodata:0007234C 02 02 02 02         ANDEQ   R0, R2, #0x20000000     ; Rd = Op1 & Op2

.rodata:0007234C             ; ---------------------------------------------------------------------------

.rodata:00072350 68 69 20 61+aHiArmHook DCB "hi arm hook",0          ; DATA XREF: .rodata:00072324r

.rodata:0007235C             ; ---------------------------------------------------------------------------


现在弄完了,别忘了恢复我们前面HOOK的四个字节.

.text:000081CC 04 B0 2D E5     STR     R11, [SP,#-4+var_s0]! ; Store to Memory


直接复制 opcode 在 00072328 这个地址补丁即可.
完事后,别忘了再跳回去.
跳回去我们直接用上面说过的 ldmfd 指令.
恢复现场
F0 87 BD E8         LDMFD   SP!, {R4-R10,PC}  // 将R4-R10 LR 出栈,满递减堆栈
现在好像已经弄完了,但是在我实验过程中,发现还是有问题的.
问题是puts的参数,应该传一个字符串指针.
这里和x86有点不一样.所以我们应该在 0007235C 处写个地址,指向 00072350. 要不然程序弄到手机上运行是会出错的.
00072324 处的也要改一下.改成  30 00 9F E5.
改完后,如下.

.rodata:00072320             loc_72320                               ; CODE XREF: .text:IsAddp

.rodata:00072320 F0 47 2D E9         STMFD   SP!, {R4-R10,LR}        ; Store Block to Memory

.rodata:00072324 30 00 9F E5         LDR     R0, =aHiArmHook         ; "hi arm hook"

.rodata:00072328 DA 62 FE EB         BL      puts                    ; Branch with Link

.rodata:0007232C 04 B0 2D E5         STR     R11, [SP,#-4]!          ; Store to Memory

.rodata:00072330 F0 87 BD E8         LDMFD   SP!, {R4-R10,PC}        ; Load Block from Memory

.rodata:00072334             ; ---------------------------------------------------------------------------

.rodata:00072334 02 02 02 02         ANDEQ   R0, R2, #0x20000000     ; Rd = Op1 & Op2

.rodata:00072338 02 02 02 02         ANDEQ   R0, R2, #0x20000000     ; Rd = Op1 & Op2

.rodata:0007233C 02 0A 02 02         ANDEQ   R0, R2, #0x2000         ; Rd = Op1 & Op2

.rodata:00072340 02 02 05 02         ANDEQ   R0, R5, #0x20000000     ; Rd = Op1 & Op2

.rodata:00072344 0E 0F 02 02         ANDEQ   R0, R2, #0x38           ; Rd = Op1 & Op2

.rodata:00072348 02 02 02 02         ANDEQ   R0, R2, #0x20000000     ; Rd = Op1 & Op2

.rodata:0007234C             loc_7234C                               ; Rd = Op1 & Op2

.rodata:0007234C 02 02 02 02         ANDEQ   R0, R2, #0x20000000

.rodata:0007234C             ; ---------------------------------------------------------------------------

.rodata:00072350 68 69 20 61+aHiArmHook DCB "hi arm hook",0          ; DATA XREF: .rodata:00072324o

.rodata:00072350 72 6D 20 68+                                        ; .rodata:off_7235Co

.rodata:0007235C 50 23 07 00 off_7235C DCD aHiArmHook                ; DATA XREF: .rodata:00072324r

.rodata:0007235C                                                     ; "hi arm hook"


在IDA里面改完后,其实并没有改完.因为IDA不支持直接在原文件里面修改.
那么我们可以通过WINHEX来修改.
在IDA里面,我们用组合快捷键. alt+f+p+d 导出dif文件. 
然后用记事本打开dif文件, 用winhex对应着dif文件来修改即可.

This difference file has been created by IDA

armhook

This difference file has been created by IDA

armhook

000001CC: 04 53

000001CD: B0 A8

000001CE: 2D 01

000001CF: E5 EB

0006A320: 02 F0

0006A321: 02 47

0006A322: 02 2D

0006A323: 02 E9

0006A324: 02 30

0006A325: 02 00

0006A326: 02 9F

0006A327: 02 E5

0006A328: 02 DA

0006A329: 02 62

0006A32A: 02 FE

0006A32B: 02 EB

0006A32C: 02 04

0006A32D: 02 B0

0006A32E: 02 2D

0006A32F: 02 E5

0006A330: 02 F0

0006A331: 02 87

0006A332: 02 BD

0006A333: 02 E8

0006A350: 02 68

0006A351: 02 69

0006A352: 02 20

0006A353: 02 61

0006A354: 02 72

0006A355: 02 6D

0006A356: 0C 20

0006A357: 02 68

0006A358: 02 6F

0006A359: 02 6F

0006A35A: 02 6B

0006A35B: 03 00

0006A35C: 02 50

0006A35D: 02 23

0006A35E: 02 07

0006A35F: 02 00



7). 赶紧传手机上测试.


上传手机:
C:\Users\john\Desktop\Tools>adb push D:\Me\Company\armhook3 /data/local/tmp/
1507 KB/s (649852 bytes in 0.421s)


8). 执行程序:


$ ls
ls
armhook
armhook_ok
$ chmod 711 armhook_ok
chmod 711 armhook_ok
$ ./armhook_ok
./armhook_ok
hi arm code1.
Please Input a Name:2010
2010
Please Input a Password:3
3
hi arm hook!
2010 + 3 = 13
error
$ ./armhook_ok
./armhook_ok
hi arm code1.
Please Input a Name:2
2
Please Input a Password:2
2
hi arm hook!
2 + 2 = 13
error
$

我们可以看到 "hi arm hook!" 字符串了,说明我们HOOK是很成功的.
但是我们可以看到我运行了2次,返回的值始终是13. 
有兴趣的可以看看是怎么回事 这里我就不做解释了,我们的arm opcode hook就这样完成了
 3:

上传的附件 bin and src.7z

注意:上传附件及图片大小不得大于30M。

⚠️ 版权声明:
本博客所有内容(含教程、源码、工具)仅供个人技术学习与研究交流使用,严禁商用、倒卖、二次分发及非法用途。
未经作者书面授权,任何组织或个人不得转载、复制或用于其他平台,违者将追究相关责任。

0 0 0 举报
复制成功