zoukankan      html  css  js  c++  java
  • 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.
    ");
    15 
    16   printf("Please Input a Name:");
    17   scanf("%d", &nNumOne);
    18 
    19   printf("
    ");
    20 
    21   printf("Please Input a Password:");
    22   scanf("%d", &nNumTwo);
    23 
    24   printf("
    ");
    25 
    26   nNumResult = IsAdd(&nNumOne, &nNumTwo);
    27 
    28   printf("%d + %d = %d
    ", nNumOne, nNumTwo, nNumResult);
    29 
    30   if(nNumResult != 2013)
    31   {
    32      printf("error
    "); 
    33   }
    34   else
    35   {
    36      printf("success
    ");
    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:MeCompany>pscp.exe -l root -pw password D:MeCompanyarmhook.c root@192.168.83.150:/root/zs/
    armhook.c                      | 0 kB |   0.6 kB/s | ETA: 00:00:00 | 100%

    D:MeCompany>


    这里我们用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:MeCompany>pscp.exe -l root -pw password root@192.168.83.150:/root/zs/armhook D:MeCompany
    armhook                        | 634 kB | 634.6 kB/s | ETA: 00:00:00 | 100%


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


    5). bin发送到手机端.


    C:UsersjohnDesktopTools>adb push d:/me/company/armhook /data/local/tmp/
    2173 KB/s (649852 bytes in 0.292s)

    C:UsersjohnDesktopTools>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.
    "
    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  ; "
    "
    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  ; "
    "
    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
    "
    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
    "
    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
    "
    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.
    "
    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                                                     ; "
    "
    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
    "
    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
    "
    87 .text:0000830C D0 FE 06 00 off_830C        DCD aSuccess            ; DATA XREF: main:loc_82D4r
    88 .text:0000830C                                                     ; "success
    "
    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
    "
    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:UsersjohnDesktopTools>adb push D:MeCompanyarmhook3 /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就这样完成了

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

  • 相关阅读:
    配置使用EF常见的一些问题及解决方案
    js定时器的使用(实例讲解)
    MySQL Workbench 修改快捷键
    Linux CentOS 启动 网卡
    Linux CentOS 安装 VMware Tools
    Linux 群晖 DokuWiki 安装
    Linux CentOS 系统安装 和 相关配置
    接口 Postman 提交json对象到后台 Request Payload
    PHP 文件上传
    电商系统 项目管理 GIT的使用
  • 原文地址:https://www.cnblogs.com/BjblCracked/p/3302914.html
Copyright © 2011-2022 走看看