arm opcode hook

/**************************************
/* 作者:半斤八兩
/* 博客:http://cnblogs.com/bjblcracked
/* 日期:2013-09-05  11:11
/**************************************



只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!


工作需要,最近一直在研究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.

代碼:

 1 #include <stdio.h>
 2 
 3 int IsAdd(int* pNumOne, int* pNumTwo)
 4 {
 5   return *pNumOne + *pNumTwo;
 6 }
 7 
 8 int main()
 9 {
10   int nNumOne = 0;
11   int nNumTwo = 0;
12   int nNumResult = 0;
13 
14   printf("hi arm code.\r\n");
15 
16   printf("Please Input a Name:");
17   scanf("%d", &nNumOne);
18 
19   printf("\r\n");
20 
21   printf("Please Input a Password:");
22   scanf("%d", &nNumTwo);
23 
24   printf("\r\n");
25 
26   nNumResult = IsAdd(&nNumOne, &nNumTwo);
27 
28   printf("%d + %d = %d\r\n", nNumOne, nNumTwo, nNumResult);
29 
30   if(nNumResult != 2013)
31   {
32      printf("error\r\n"); 
33   }
34   else
35   {
36      printf("success\r\n");
37   }
38 
39   return 1;
40 }

 

测试代码,写的不严谨.


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来看看程序.

代碼:

 1 .text:00008204             ; =============== S U B R O U T I N E =======================================
 2 .text:00008204             ; Attributes: noreturn bp-based frame
 3 .text:00008204                             EXPORT main
 4 .text:00008204             main                                    ; DATA XREF: _start+20o
 5 .text:00008204                                                     ; .text:off_8154o
 6 .text:00008204             var_10          = -0x10
 7 .text:00008204             var_C           = -0xC
 8 .text:00008204             var_8           = -8
 9 .text:00008204 00 48 2D E9                 STMFD   SP!, {R11,LR}   ; Store Block to Memory
10 .text:00008208 04 B0 8D E2                 ADD     R11, SP, #4     ; Rd = Op1 + Op2
11 .text:0000820C 10 D0 4D E2                 SUB     SP, SP, #0x10   ; Rd = Op1 - Op2
12 .text:00008210 00 30 A0 E3                 MOV     R3, #0          ; Rd = Op2
13 .text:00008214 0C 30 0B E5                 STR     R3, [R11,#var_C] ; Store to Memory
14 .text:00008218 00 30 A0 E3                 MOV     R3, #0          ; Rd = Op2
15 .text:0000821C 10 30 0B E5                 STR     R3, [R11,#var_10] ; Store to Memory
16 .text:00008220 00 30 A0 E3                 MOV     R3, #0          ; Rd = Op2
17 .text:00008224 08 30 0B E5                 STR     R3, [R11,#var_8] ; Store to Memory
18 .text:00008228 BC 00 9F E5                 LDR     R0, =aHiArmCode_ ; "hi arm code.\r"
19 .text:0000822C 19 0B 00 EB                 BL      puts            ; Branch with Link
20 .text:00008230 B8 30 9F E5                 LDR     R3, =aPleaseInputANa ; "Please Input a Name:"
21 .text:00008234 03 00 A0 E1                 MOV     R0, R3          ; Rd = Op2
22 .text:00008238 80 0A 00 EB                 BL      printf          ; Branch with Link
23 .text:0000823C B0 20 9F E5                 LDR     R2, =aD         ; "%d"
24 .text:00008240 0C 30 4B E2                 SUB     R3, R11, #-var_C ; Rd = Op1 - Op2
25 .text:00008244 02 00 A0 E1                 MOV     R0, R2          ; Rd = Op2
26 .text:00008248 03 10 A0 E1                 MOV     R1, R3          ; Rd = Op2
27 .text:0000824C 8A 0A 00 EB                 BL      __isoc99_scanf  ; Branch with Link
28 .text:00008250 A0 00 9F E5                 LDR     R0, =asc_6FE98  ; "\r"
29 .text:00008254 0F 0B 00 EB                 BL      puts            ; Branch with Link
30 .text:00008258 9C 30 9F E5                 LDR     R3, =aPleaseInputAPa ; "Please Input a Password:"
31 .text:0000825C 03 00 A0 E1                 MOV     R0, R3          ; Rd = Op2
32 .text:00008260 76 0A 00 EB                 BL      printf          ; Branch with Link
33 .text:00008264 88 20 9F E5                 LDR     R2, =aD         ; "%d"
34 .text:00008268 10 30 4B E2                 SUB     R3, R11, #-var_10 ; Rd = Op1 - Op2
35 .text:0000826C 02 00 A0 E1                 MOV     R0, R2          ; Rd = Op2
36 .text:00008270 03 10 A0 E1                 MOV     R1, R3          ; Rd = Op2
37 .text:00008274 80 0A 00 EB                 BL      __isoc99_scanf  ; Branch with Link
38 .text:00008278 78 00 9F E5                 LDR     R0, =asc_6FE98  ; "\r"
39 .text:0000827C 05 0B 00 EB                 BL      puts            ; Branch with Link
40 .text:00008280 0C 20 4B E2                 SUB     R2, R11, #-var_C ; Rd = Op1 - Op2
41 .text:00008284 10 30 4B E2                 SUB     R3, R11, #-var_10 ; Rd = Op1 - Op2
42 .text:00008288 02 00 A0 E1                 MOV     R0, R2          ; Rd = Op2
43 .text:0000828C 03 10 A0 E1                 MOV     R1, R3          ; Rd = Op2
44 .text:00008290 CD FF FF EB                 BL      IsAdd           ; Branch with Link
45 .text:00008294 08 00 0B E5                 STR     R0, [R11,#var_8] ; Store to Memory
46 .text:00008298 60 10 9F E5                 LDR     R1, =aDDD       ; "%d + %d = %d\r\n"
47 .text:0000829C 0C 20 1B E5                 LDR     R2, [R11,#var_C] ; Load from Memory
48 .text:000082A0 10 30 1B E5                 LDR     R3, [R11,#var_10] ; Load from Memory
49 .text:000082A4 01 00 A0 E1                 MOV     R0, R1          ; Rd = Op2
50 .text:000082A8 02 10 A0 E1                 MOV     R1, R2          ; Rd = Op2
51 .text:000082AC 03 20 A0 E1                 MOV     R2, R3          ; Rd = Op2
52 .text:000082B0 08 30 1B E5                 LDR     R3, [R11,#var_8] ; Load from Memory
53 .text:000082B4 61 0A 00 EB                 BL      printf          ; Branch with Link
54 .text:000082B8 08 20 1B E5                 LDR     R2, [R11,#var_8] ; Load from Memory
55 .text:000082BC 40 30 9F E5                 LDR     R3, =0x7DD      ; Load from Memory
56 .text:000082C0 03 00 52 E1                 CMP     R2, R3          ; Set cond. codes on Op1 - Op2
57 .text:000082C4 02 00 00 0A                 BEQ     loc_82D4        ; Branch
58 .text:000082C8 38 00 9F E5                 LDR     R0, =aError     ; "error\r"
59 .text:000082CC F1 0A 00 EB                 BL      puts            ; Branch with Link
60 .text:000082D0 01 00 00 EA                 B       loc_82DC        ; Branch
61 .text:000082D4             loc_82D4                                ; CODE XREF: main+C0j
62 .text:000082D4 30 00 9F E5                 LDR     R0, =aSuccess   ; "success\r"
63 .text:000082D8 EE 0A 00 EB                 BL      puts            ; Branch with Link
64 .text:000082DC             loc_82DC                                ; CODE XREF: main+CCj
65 .text:000082DC 01 30 A0 E3                 MOV     R3, #1          ; Rd = Op2
66 .text:000082E0 03 00 A0 E1                 MOV     R0, R3          ; Rd = Op2
67 .text:000082E4 04 D0 4B E2                 SUB     SP, R11, #4     ; Rd = Op1 - Op2
68 .text:000082E8 00 88 BD E8                 LDMFD   SP!, {R11,PC}   ; Load Block from Memory
69 .text:000082E8             ; End of function main
70 .text:000082EC 6C FE 06 00 off_82EC        DCD aHiArmCode_         ; DATA XREF: main+24r
71 .text:000082EC                                                     ; "hi arm code.\r"
72 .text:000082F0 7C FE 06 00 off_82F0        DCD aPleaseInputANa     ; DATA XREF: main+2Cr
73 .text:000082F0                                                     ; "Please Input a Name:"
74 .text:000082F4 94 FE 06 00 off_82F4        DCD aD                  ; DATA XREF: main+38r
75 .text:000082F4                                                     ; main+60r
76 .text:000082F4                                                     ; "%d"
77 .text:000082F8 98 FE 06 00 off_82F8        DCD asc_6FE98           ; DATA XREF: main+4Cr
78 .text:000082F8                                                     ; main+74r
79 .text:000082F8                                                     ; "\r"
80 .text:000082FC 9C FE 06 00 off_82FC        DCD aPleaseInputAPa     ; DATA XREF: main+54r
81 .text:000082FC                                                     ; "Please Input a Password:"
82 .text:00008300 B8 FE 06 00 off_8300        DCD aDDD                ; DATA XREF: main+94r
83 .text:00008300                                                     ; "%d + %d = %d\r\n"
84 .text:00008304 DD 07 00 00 dword_8304      DCD 0x7DD               ; DATA XREF: main+B8r
85 .text:00008308 C8 FE 06 00 off_8308        DCD aError              ; DATA XREF: main+C4r
86 .text:00008308                                                     ; "error\r"
87 .text:0000830C D0 FE 06 00 off_830C        DCD aSuccess            ; DATA XREF: main:loc_82D4r
88 .text:0000830C                                                     ; "success\r"
89 .text:00008310             ; =============== S U B R O U T I N E =======================================

 


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

代碼:

1 .text:000082B8             ; ---------------------------------------------------------------------------
2 .text:000082B8 08 20 1B E5                 LDR     R2, [R11,#var_8] ; Load from Memory
3 .text:000082BC 40 30 9F E5                 LDR     R3, =0x7DD      ; Load from Memory
4 .text:000082C0 03 00 52 E1                 CMP     R2, R3          ; Set cond. codes on Op1 - Op2
5 .text:000082C4 02 00 00 0A                 BEQ     loc_82D4        ; Branch
6 .text:000082C8 38 00 9F E5                 LDR     R0, =aError     ; "error\r"
7 .text:000082CC F1 0A 00 EB                 BL      puts            ; Branch with Link
8 .text:000082D0 01 00 00 EA                 B       loc_82DC        ; Branch
9 .text:000082D4             ; ---------------------------------------------------------------------------

 


我们只要把beq改成 bne就可以了.
或者直接改成 B   loc_82D4 .这样都可以实现爆破.

文本重点是讲HOOK,就不多说破解过程了.

CM写的很简洁,就一个isadd函数,那么我们就来尝试HOOK IsAdd函数.

代碼:
 1 .text:000081CC                             EXPORT IsAdd
 2 .text:000081CC             IsAdd                                   ; CODE XREF: main+8Cp
 3 .text:000081CC 04 B0 2D E5                 STR     R11, [SP,#-4]!  ; Store to Memory
 4 .text:000081D0 00 B0 8D E2                 ADD     R11, SP, #0     ; Rd = Op1 + Op2
 5 .text:000081D4 0C D0 4D E2                 SUB     SP, SP, #0xC    ; Rd = Op1 - Op2
 6 .text:000081D8 08 00 0B E5                 STR     R0, [R11,#-8]   ; Store to Memory
 7 .text:000081DC 0C 10 0B E5                 STR     R1, [R11,#-0xC] ; Store to Memory
 8 .text:000081E0 08 30 1B E5                 LDR     R3, [R11,#-8]   ; Load from Memory
 9 .text:000081E4 00 20 93 E5                 LDR     R2, [R3]        ; Load from Memory
10 .text:000081E8 0C 30 1B E5                 LDR     R3, [R11,#-0xC] ; Load from Memory
11 .text:000081EC 00 30 93 E5                 LDR     R3, [R3]        ; Load from Memory
12 .text:000081F0 03 30 82 E0                 ADD     R3, R2, R3      ; Rd = Op1 + Op2
13 .text:000081F4 03 00 A0 E1                 MOV     R0, R3          ; Rd = Op2
14 .text:000081F8 00 D0 8B E2                 MOV     SP, R11         ; Rd = Op2
15 .text:000081FC 04 B0 9D E4                 LDR     R11, [SP],#4    ; Load from Memory
16 .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


 
不明看例:)

代碼:
1 ROM:9D039D3C 108 1C 00 00 1A                 BNE     loc_9D039DB4    ; Branch
2 (9D039DB4 - 9D039D3C) / 4 - 2 = 1c
3 9D039D3C + (1c + 2) * 4 = 9D039DB4
4 
5 
6 
7 ROM:9D039D90 108 07 00 00 EA                 B       loc_9D039DB4    ; Branch
8 (9D039DB4 - 9D039D90) / 4 - 2 = 7
9 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

下面我们再程序中找段空数据地址.

代碼:
1 .rodata:00072320 02 02 02 02                 ANDEQ   R0, R2, #0x20000000 ; Rd = Op1 & Op2
2 .rodata:00072324 02 02 02 02                 ANDEQ   R0, R2, #0x20000000 ; Rd = Op1 & Op2
3 .rodata:00072328 02 02 02 02                 ANDEQ   R0, R2, #0x20000000 ; Rd = Op1 & Op2
4 .rodata:0007232C 02 02 02 02                 ANDEQ   R0, R2, #0x20000000 ; Rd = Op1 & Op2
5 .rodata:00072330 02 02 02 02                 ANDEQ   R0, R2, #0x20000000 ; Rd = Op1 & Op2
6 .rodata:00072334 02 02 02 02                 ANDEQ   R0, R2, #0x20000000 ; Rd = Op1 & Op2
7 .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 然后确定就行了.
改了后如下效果.


[COLOR="red"]

 1 .text:000081CC             IsAdd                                   ; CODE XREF: main+8Cp
 2 .text:000081CC 53 A8 01 EB                 BL      loc_72320       ; Branch with Link
 3 .text:000081D0 00 B0 8D E2                 ADD     R11, SP, #0     ; Rd = Op1 + Op2
 4 .text:000081D4 0C D0 4D E2                 SUB     SP, SP, #0xC    ; Rd = Op1 - Op2
 5 .text:000081D8 08 00 0B E5                 STR     R0, [R11,#-8]   ; Store to Memory
 6 .text:000081DC 0C 10 0B E5                 STR     R1, [R11,#-0xC] ; Store to Memory
 7 .text:000081E0 08 30 1B E5                 LDR     R3, [R11,#-8]   ; Load from Memory
 8 .text:000081E4 00 20 93 E5                 LDR     R2, [R3]        ; Load from Memory
 9 .text:000081E8 0C 30 1B E5                 LDR     R3, [R11,#-0xC] ; Load from Memory
10 .text:000081EC 00 30 93 E5                 LDR     R3, [R3]        ; Load from Memory
11 .text:000081F0 03 30 82 E0                 ADD     R3, R2, R3      ; Rd = Op1 + Op2
12 .text:000081F4 03 00 A0 E1                 MOV     R0, R3          ; Rd = Op2
13 .text:000081F8 00 D0 8B E2                 MOV     SP, R11         ; Rd = Op2
14 .text:000081FC 04 B0 9D E4                 LDR     R11, [SP],#4    ; Load from Memory
15 .text:00008200 1E FF 2F E1                 BX      LR              ; Branch to/from Thumb mode

[/CODE]


注意看81cc处的指令已经被我们改了.
现在我们要到 loc_72310 这里, 
我们就来打印一个"hi arm hook" 吧.
打印的话,我们要调用 puts 函数,
我们来看一下函数地址.

代碼:
 1 .text:0000AE98             puts                                    ; CODE XREF: main+28p
 2 .text:0000AE98                                                     ; main+50p ...
 3 .text:0000AE98 F0 47 2D E9                 STMFD   SP!, {R4-R10,LR} ; Alternative name is '_IO_puts'
 4 .text:0000AE9C 00 90 A0 E1                 MOV     R9, R0          ; Rd = Op2
 5 .text:0000AEA0 1E 27 00 EB                 BL      strlen          ; Branch with Link
 6 .text:0000AEA4 3C 72 9F E5                 LDR     R7, =stdout     ; Load from Memory
 7 .text:0000AEA8 00 60 97 E5                 LDR     R6, [R7]        ; Load from Memory
 8 .text:0000AEAC 00 40 96 E5                 LDR     R4, [R6]        ; Load from Memory
 9 .text:0000AEB0 02 49 14 E2                 ANDS    R4, R4, #0x8000 ; Rd = Op1 & Op2
10 .text:0000AEB4 00 A0 A0 E1                 MOV     R10, R0         ; Rd = Op2
11 .text:0000AEB8 59 00 00 1A                 BNE     loc_B024        ; Branch
12 .text:0000AEBC 48 50 96 E5                 LDR     R5, [R6,#0x48]  ; Load from Memory
13 .text:0000AEC0 B2 FD FF EB                 BL      __aeabi_read_tp ; Branch with Link
14 .text:0000AEC4 08 30 95 E5                 LDR     R3, [R5,#8]     ; Load from Memory
15 .text:0000AEC8 13 8D 40 E2                 SUB     R8, R0, #0x4C0  ; Rd = Op1 - Op2
16 .text:0000AECC 08 00 53 E1                 CMP     R3, R8          ; Set cond. codes on Op1 - Op2
17 .text:0000AED0 0E 00 00 0A                 BEQ     loc_AF10        ; Branch
18 .text:0000AED4 01 10 A0 E3                 MOV     R1, #1          ; Rd = Op2
19 .text:0000AED8 05 20 A0 E1                 MOV     R2, R5          ; Rd = Op2
20 ...
21 ...

 

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" 

代碼:
 1 .rodata:00072320 02 02 02 02     ANDEQ   R0, R2, #0x20000000         ; Rd = Op1 & Op2
 2 .rodata:00072324 02 02 02 02     ANDEQ   R0, R2, #0x20000000         ; Rd = Op1 & Op2
 3 .rodata:00072328 02 02 02 02     ANDEQ   R0, R2, #0x20000000         ; Rd = Op1 & Op2
 4 .rodata:0007232C 02 02 02 02     ANDEQ   R0, R2, #0x20000000         ; Rd = Op1 & Op2
 5 .rodata:00072330 02 02 02 02     ANDEQ   R0, R2, #0x20000000         ; Rd = Op1 & Op2
 6 .rodata:00072334 02 02 02 02     ANDEQ   R0, R2, #0x20000000         ; Rd = Op1 & Op2
 7 .rodata:00072338 02 02 02 02     ANDEQ   R0, R2, #0x20000000         ; Rd = Op1 & Op2
 8 .rodata:0007233C 02 0A 02 02     ANDEQ   R0, R2, #0x2000             ; Rd = Op1 & Op2
 9 .rodata:00072340 02 02 05 02     ANDEQ   R0, R5, #0x20000000         ; Rd = Op1 & Op2
10 .rodata:00072344 0E 0F 02 02     ANDEQ   R0, R2, #0x38               ; Rd = Op1 & Op2
11 .rodata:00072348 02 02 02 02     ANDEQ   R0, R2, #0x20000000         ; Rd = Op1 & Op2
12 .rodata:0007234C 02 02 02 02     ANDEQ   R0, R2, #0x20000000         ; Rd = Op1 & Op2
13 .rodata:0007234C             ; ---------------------------------------------------------------------------
14 .rodata:00072350 68 69 20 61+aHiArmHook DCB "hi arm hook",0
15 .rodata:0007235C             ; ---------------------------------------------------------------------------
16 .rodata:0007235C 02 02 02 02     ANDEQ   R0, R2, #0x20000000         ; Rd = Op1 & Op2
17 .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

代碼:
 1 .rodata:00072320 F0 47 2D E9         STMFD   SP!, {R4-R10,LR}        ; Store Block to Memory
 2 .rodata:00072324 24 00 9F E5         LDR     R0, aHiArmHook          ; "hi arm hook"
 3 .rodata:00072328 02 02 02 02         ANDEQ   R0, R2, #0x20000000     ; Rd = Op1 & Op2
 4 .rodata:0007232C 02 02 02 02         ANDEQ   R0, R2, #0x20000000     ; Rd = Op1 & Op2
 5 .rodata:00072330 02 02 02 02         ANDEQ   R0, R2, #0x20000000     ; Rd = Op1 & Op2
 6 .rodata:00072334 02 02 02 02         ANDEQ   R0, R2, #0x20000000     ; Rd = Op1 & Op2
 7 .rodata:00072338 02 02 02 02         ANDEQ   R0, R2, #0x20000000     ; Rd = Op1 & Op2
 8 .rodata:0007233C 02 0A 02 02         ANDEQ   R0, R2, #0x2000         ; Rd = Op1 & Op2
 9 .rodata:00072340 02 02 05 02         ANDEQ   R0, R5, #0x20000000     ; Rd = Op1 & Op2
10 .rodata:00072344 0E 0F 02 02         ANDEQ   R0, R2, #0x38           ; Rd = Op1 & Op2
11 .rodata:00072348 02 02 02 02         ANDEQ   R0, R2, #0x20000000     ; Rd = Op1 & Op2
12 .rodata:0007234C 02 02 02 02         ANDEQ   R0, R2, #0x20000000     ; Rd = Op1 & Op2
13 .rodata:0007234C             ; ---------------------------------------------------------------------------
14 .rodata:00072350 68 69 20 61+aHiArmHook DCB "hi arm hook",0          ; DATA XREF: .rodata:00072324r
15 .rodata:0007235C             ; ---------------------------------------------------------------------------
16 .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

代碼:
 1 .rodata:00072320             loc_72320                               ; CODE XREF: .text:IsAddp
 2 .rodata:00072320 F0 47 2D E9         STMFD   SP!, {R4-R10,LR}        ; Store Block to Memory
 3 .rodata:00072324 24 00 9F E5         LDR     R0, aHiArmHook          ; "hi arm hook"
 4 .rodata:00072328 DA 62 FE EB         BL      puts                    ; Branch with Link
 5 .rodata:0007232C 02 02 02 02         ANDEQ   R0, R2, #0x20000000     ; Rd = Op1 & Op2
 6 .rodata:00072330 02 02 02 02         ANDEQ   R0, R2, #0x20000000     ; Rd = Op1 & Op2
 7 .rodata:00072334 02 02 02 02         ANDEQ   R0, R2, #0x20000000     ; Rd = Op1 & Op2
 8 .rodata:00072338 02 02 02 02         ANDEQ   R0, R2, #0x20000000     ; Rd = Op1 & Op2
 9 .rodata:0007233C 02 0A 02 02         ANDEQ   R0, R2, #0x2000         ; Rd = Op1 & Op2
10 .rodata:00072340 02 02 05 02         ANDEQ   R0, R5, #0x20000000     ; Rd = Op1 & Op2
11 .rodata:00072344 0E 0F 02 02         ANDEQ   R0, R2, #0x38           ; Rd = Op1 & Op2
12 .rodata:00072348 02 02 02 02         ANDEQ   R0, R2, #0x20000000     ; Rd = Op1 & Op2
13 .rodata:0007234C 02 02 02 02         ANDEQ   R0, R2, #0x20000000     ; Rd = Op1 & Op2
14 .rodata:0007234C             ; ---------------------------------------------------------------------------
15 .rodata:00072350 68 69 20 61+aHiArmHook DCB "hi arm hook",0          ; DATA XREF: .rodata:00072324r
16 .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.

改完后,如下.

代碼:
 1 .rodata:00072320             loc_72320                               ; CODE XREF: .text:IsAddp
 2 .rodata:00072320 F0 47 2D E9         STMFD   SP!, {R4-R10,LR}        ; Store Block to Memory
 3 .rodata:00072324 30 00 9F E5         LDR     R0, =aHiArmHook         ; "hi arm hook"
 4 .rodata:00072328 DA 62 FE EB         BL      puts                    ; Branch with Link
 5 .rodata:0007232C 04 B0 2D E5         STR     R11, [SP,#-4]!          ; Store to Memory
 6 .rodata:00072330 F0 87 BD E8         LDMFD   SP!, {R4-R10,PC}        ; Load Block from Memory
 7 .rodata:00072334             ; ---------------------------------------------------------------------------
 8 .rodata:00072334 02 02 02 02         ANDEQ   R0, R2, #0x20000000     ; Rd = Op1 & Op2
 9 .rodata:00072338 02 02 02 02         ANDEQ   R0, R2, #0x20000000     ; Rd = Op1 & Op2
10 .rodata:0007233C 02 0A 02 02         ANDEQ   R0, R2, #0x2000         ; Rd = Op1 & Op2
11 .rodata:00072340 02 02 05 02         ANDEQ   R0, R5, #0x20000000     ; Rd = Op1 & Op2
12 .rodata:00072344 0E 0F 02 02         ANDEQ   R0, R2, #0x38           ; Rd = Op1 & Op2
13 .rodata:00072348 02 02 02 02         ANDEQ   R0, R2, #0x20000000     ; Rd = Op1 & Op2
14 .rodata:0007234C             loc_7234C                               ; Rd = Op1 & Op2
15 .rodata:0007234C 02 02 02 02         ANDEQ   R0, R2, #0x20000000
16 .rodata:0007234C             ; ---------------------------------------------------------------------------
17 .rodata:00072350 68 69 20 61+aHiArmHook DCB "hi arm hook",0          ; DATA XREF: .rodata:00072324o
18 .rodata:00072350 72 6D 20 68+                                        ; .rodata:off_7235Co
19 .rodata:0007235C 50 23 07 00 off_7235C DCD aHiArmHook                ; DATA XREF: .rodata:00072324r
20 .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就这样完成了

 

源码和程序下载地址:看雪学院

posted @ 2013-09-05 11:23  半斤八兩  阅读(2026)  评论(1编辑  收藏  举报