<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>

新聞中心

EEPW首頁(yè) > 嵌入式系統 > 設計應用 > android平臺arm指令學(xué)習和調試

android平臺arm指令學(xué)習和調試

作者: 時(shí)間:2016-11-09 來(lái)源:網(wǎng)絡(luò ) 收藏
*/

一、Ndk下內聯(lián)匯編

跟vc下一樣,ndk編譯環(huán)境下也能使用內聯(lián)匯編,如下:

本文引用地址:http://dyxdggzs.com/article/201611/317575.htm

include

intmy_thumb(intdummy)

{

__asm__(

“movr0,#1tn”

“movr1,#2tn”

“addr0,r0,r1tn”

“bxlr”

);

}

intmain()

{

intn=my_thumb(12);

printf(“result:%08x”,n);

return0;

}

再看看使用標簽的例子:

#include

intmy_thumb(intdummy)

{

__asm(

“movr0,#0x1tn”

“ldrr0,__starttn”

“adrr0,__starttn”

“ldrr0,=__starttn”

“__start:tn”

“noptn”

);

}

intmain()

{

intn=my_thumb(12);

printf(“result:%08x”,n);

return0;

}

二、編譯

創(chuàng )建android.mk文件,然后使用ndk-build進(jìn)行編譯

1)編譯一個(gè)可執行程序,Android.mk文件的內容如下:

LOCAL_PATH:=$(callmy-dir)

include$(CLEAR_VARS)

LOCAL_MODULE:=helloa

LOCAL_SRC_FILES:=testHello.c

include$(BUILD_EXECUTABLE)

2)編譯一個(gè)so,android.mk文件內容如下:

LOCAL_PATH:=$(callmy-dir)

include$(CLEAR_VARS)

LOCAL_MODULE:=testJniSo

LOCAL_SRC_FILES:=testJniSo.c

include$(BUILD_SHARED_LIBRARY)

3)必須有一個(gè)jni目錄,目錄結構:

4)這樣之后,就可以在cmd窗口中,切換到代碼目錄,使用ndk-build命令進(jìn)行編譯。

三、調試可執行程序

1)Push編譯好的elf到樣機中

2)使用gdbserver啟動(dòng)該文件

“/data/local/gdbserver:12345/data/local/helloa”

3)adbforwardtcp:12345tcp:12345

4)啟動(dòng)gdb

5)Targetremote127.0.0.1:12345

6)Ni是單步,setdisassemble-nexton下一句指令顯示反匯編,使用setarmforce-modearm或者setarmforce-modethumb讓gdb切換thumb和arm代碼顯示。

7)Display/i$pc顯示當前的代碼

8)Continue就是windbg的f5,od的f9

9)Infobreakpoints顯示斷點(diǎn),而delete刪除斷點(diǎn)disable禁用斷點(diǎn)

10)Disas0xAAAA,+20(20字節的數據)顯示反匯編

11)調試比較



Gdbarm和ida反匯編比較:

四、調試so

以愛(ài)加密為例,進(jìn)行調試,范例是看雪求助帖給出的,鏈接如下:

http://bbs.pediy.com/showthread.php?t=184375

調試方法

1)So中實(shí)現的方法,程序跑起來(lái)再附加的話(huà),該方法可能已經(jīng)執行完??囱┥辖o出方法步驟較多,應用和底層都調試,有點(diǎn)復雜如下:

我試出來(lái)的方法,對so文件進(jìn)行修改,讓其在入口處直接調用它本身。需要注意的是,必須在so的入口函數處修改,如果在內部調用函數修改,app會(huì )自動(dòng)退出。

2)gdb的調試,使用ndk下自帶的gdbserver和gdb進(jìn)行調試

3)將修改的so導入到手機該應用的lib目錄下,覆蓋之前的so文件。然后運行app,出現只有邊界的黑框。Gdbserver附加,使用set命令,將bl調用自身的命令改回去,則可以進(jìn)行正常調試了。

4)模塊基地址的獲取cat/proc/pid/maps找到

5)Dump內存的命令式dumpbinarymemoryc:xxxstartAdendAd

6)小細節要注意的是:.init_proc的地址是0x31cb9,ida直接點(diǎn)過(guò)去,是一堆數據,摁c無(wú)法轉成代碼

因為arm指令和thumb指令是2字節或者4字節對齊的,所以,改地址加1應該是真正的地址。將該地址修改為調用自身,然后gdb附加,成功斷下來(lái),然后輸入“ir$lr”查看返回值,如下

該地址恰巧是在linker模塊中,

此處的在linker中的代碼如下:

7)至于為什么系統的linker會(huì )調用.init_proc,不得而知。該so的oep為空,沒(méi)有section表,但是有dynamicsection表。自己寫(xiě)一個(gè)so,并沒(méi)有函數“init_proc”的導出,需要再研究下elf文件格式。

自解碼

本身的so是經(jīng)過(guò)加密的,解密的代碼是在.init_proc+1的位置,字節碼的代碼較長(cháng),部分代碼如下:

1)windows下逃避斷點(diǎn)的方法,就是利用“codeshadow”的方式,在申請內存,然后將代碼拷貝到指定的申請的空間上執行,這樣,直接斷原代碼是斷不到的。但是,直接搜索二進(jìn)制就可以找到這樣的鏡像代碼。

如下,之前應該運行的代碼:

拷貝到其它地方執行的代碼:

2)計算指定函數的匯編指令長(cháng)度:代碼要進(jìn)行拷貝執行,必須計算拷貝代碼的長(cháng)度。愛(ài)加密計算拷貝代碼的長(cháng)度方式是通過(guò)call來(lái)計算的。函數實(shí)現的排布如下:

__asmcalltargetFunc

xxxxxx

xxxxxx

xxxxxx

xxxxxx

xxxxxx

xxxxxx

VoidtargetFunc

而call的指令是:

00f0是指令opcode,c0與跳轉的距離有關(guān),計算公式是(targetAddr–curAddr)/2–2=opdataLen。那么知道c0就知道中間xxx代碼的長(cháng)度了。

3)愛(ài)加密處理的數據有三塊,第一塊未知,第二塊是壓縮過(guò)的指令數據,第三塊是需要拷貝到堆上的代碼,這三塊數據總長(cháng)度為0x29e3c,使用mmap2進(jìn)行申請映射內存,如下:

然后將三塊數據拷貝到映射的內存上,

在此之后,數據內存排布:

AAAAAAAAA

BBBBBBBBBB

CCCCCCCCCC

愛(ài)加密還原代碼前,處理了三塊數據,如上。其中,“AAAAAAAAAA”數據是一組未使用過(guò)的數據,具體功能未知,長(cháng)度為0x6b0;“BBBBBBBBBB”代表的是lzma壓縮過(guò)的數據;“CCCCCCCCCC”代表的是拷貝函數的數據(一共拷貝三個(gè)函數的代碼)。

4)修改lr,然后刷新cache,返回到mmap2得到的堆上的函數進(jìn)行執行

OAD:510A4010 01 1C MOVS R1, R0 ; r0 0x4fb83e3c
LOAD:510A4012 10 1C MOVS R0, R2 ; r2 0x4fb83bd8
LOAD:510A4014 BE 46 MOV LR, R7 ; r7 0x4fb83d91
LOAD:510A4014 ; 這里對lr寄存器進(jìn)行修改
LOAD:510A4016 C3 E7 B libexec___ARM_NR_cacheflush

5)再次調用mmap2,抹掉最初的“AA”、“BB”和“CC”三塊數據,這樣,之前執行的代碼和數據將都被清零。這三塊數據就被搬運到第一次調用mmap2得到的地址上,數據在內存重新做了排布。

6)解壓數據:將數據解壓到第二次調用mmap2清零的地址上,偏移為0x6b0。數據的解壓使用的是lzma算法,解壓的代碼:

上圖中,r4指向的lzma的解壓函數,r0是待解壓的數據,r1是待解壓的長(cháng)度,r2是解壓到的地址,r3上是保存解壓到的地址空間的長(cháng)度的地址。Lzma的具體實(shí)現:

7)修正指定數據:解壓完的數據并不是最終的代碼,還需要進(jìn)行修正。修正代碼如下:

修正的方法是:解壓后的數據從末端開(kāi)始往前,每四字節為單位,如果這四字的最高個(gè)字節是低四位是0xb,則進(jìn)行移位修復。(這種方法很像pe殼中解密代碼后,對0xe8、0xe9、0xff25等的修復)修復代碼如下:

8)修改內存屬性,代碼就完全解密,并可以運行了。

解密前的導出函數代碼如下:

顯然上圖中的代碼沒(méi)法運行,解碼后的代碼如下:

解碼后的代碼分析

解密后的代碼上邊已經(jīng)給出,r0傳遞的就是jnienv虛表指針,gdb中顯示相關(guān)api在libicuil8n.so模塊中,如下:

1)動(dòng)態(tài)注冊接口:解密后的代碼主要是動(dòng)態(tài)注冊用于java調用的接口,如下:

2)load的實(shí)現

3)run方法的實(shí)現

gdb調試的問(wèn)題:

1)Gdb在遇到bxpc;nop指令,從thumb指令切換到arm指令時(shí),會(huì )出錯,調試無(wú)法繼續進(jìn)行。解決方法:

http://sourceware-org.1504.n7.nabble.com/Fix-ARM-stepping-over-Thumb-mode-quot-bx-pc-quot-or-quot-blx-pc-quot-td69213.html)

2)gdb遇到如下的拷貝指令也會(huì )退出調試,解決方法是跳過(guò)這段代碼的位置下斷點(diǎn)。

LOAD:510A3F88 loc_510A3F88 ; CODE XREF: libexec_memcopy+1Ej
LOAD:510A3F88 DC 13 B1 E8 LDMIA R1!, {R2-R4,R6-R9,R12}
LOAD:510A3F8C 01 50 55 E2 SUBS R5, R5, #1 ; 這里r5不斷的減少
LOAD:510A3F90 DC 13 A0 E8 STMIA R0!, {R2-R4,R6-R9,R12}
LOAD:510A3F94 FB FF FF 1A BNE loc_510A3F88
LOAD:510A3F98 D4 03 BD E8 LDMFD SP!, {R2,R4,R6-R9}



評論


技術(shù)專(zhuān)區

關(guān)閉
国产精品自在自线亚洲|国产精品无圣光一区二区|国产日产欧洲无码视频|久久久一本精品99久久K精品66|欧美人与动牲交片免费播放
<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>