最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

Unidbg調(diào)試so

2021-08-24 15:05 作者:無情劍客Burning  | 我要投稿


在 Android逆向之ARM64靜態(tài)分析 對(duì)ARM64匯編進(jìn)行了介紹,網(wǎng)傳ARMV9要出來了,難道又要重新學(xué)習(xí)ARMV9? 在Frida高級(jí)篇-免ROOT使用Frida(不修改源代碼) 中對(duì)elf文件進(jìn)行了介紹,本文使用unidbg模擬執(zhí)行so來分析native方法。首先來介紹Unicorn。

Unicorn

Unicorn is a lightweight multi-platform, multi-architecture CPU emulator framework.

本文使用無名俠大神使用的Unicorn入門教程來看看Unicorn是怎么模擬CPU的。

  1. from unicorn import *

  2. from unicorn.arm_const import *

  3. from capstone import *


  4. ARM_CODE = b"\x37\x00\xa0\xe3\x03\x10\x42\xe0"


  5. # Disassemble ARM32 binary

  6. md = Cs(CS_ARCH_ARM, CS_MODE_ARM)

  7. for i in md.disasm(ARM_CODE, 0x1000):

  8. print("0x%x:\t%s\t%s" %(i.address, i.mnemonic, i.op_str))



  9. # mov r0, #0x37;

  10. # sub r1, r2, r3

  11. # Test ARM


  12. # callback for tracing instructions

  13. def hook_code(uc, address, size, user_data):

  14. print(">>> Tracing instruction at 0x%x, instruction size = 0x%x" % (address, size))


  15. def test_arm():

  16. print("Emulate ARM code")

  17. try:

  18. # Initialize emulator in ARM mode

  19. ? ? ? ?mu = Uc(UC_ARCH_ARM, UC_MODE_THUMB)


  20. # map 2MB memory for this emulation

  21. ? ? ? ?ADDRESS = 0x10000

  22. ? ? ? ?mu.mem_map(ADDRESS, 2 * 0x10000)

  23. ? ? ? ?mu.mem_write(ADDRESS, ARM_CODE)


  24. ? ? ? ?mu.reg_write(UC_ARM_REG_R0, 0x1234)

  25. ? ? ? ?mu.reg_write(UC_ARM_REG_R2, 0x6789)

  26. ? ? ? ?mu.reg_write(UC_ARM_REG_R3, 0x3333)


  27. ? ? ? ?mu.hook_add(UC_HOOK_CODE, hook_code, begin=ADDRESS, end=ADDRESS+8)

  28. # emulate machine code in infinite time

  29. ? ? ? ?mu.emu_start(ADDRESS, ADDRESS + len(ARM_CODE))

  30. ? ? ? ?r0 = mu.reg_read(UC_ARM_REG_R0)

  31. ? ? ? ?r1 = mu.reg_read(UC_ARM_REG_R1)

  32. print(">>> R0 = 0x%x" % r0)

  33. print(">>> R1 = 0x%x" % r1)

  34. except UcError as e:

  35. print("ERROR: %s" % e)



  36. test_arm()

運(yùn)行結(jié)果:

添加指令級(jí)的Hook

這個(gè)有點(diǎn)像單步調(diào)試的感覺。

  1. mu.hook_add(UC_HOOK_CODE, hook_code, begin=ADDRESS, end=ADDRESS)

在begin...end范圍內(nèi)的每一條指令被執(zhí)行前都會(huì)調(diào)用callback。

讓我們來看看hook_code 的實(shí)現(xiàn)吧

  1. # callback for tracing instructions

  2. def hook_code(uc, address, size, user_data):

  3. print(">>> Tracing instruction at 0x%x, instruction size = 0x%x" %(address, size))

這段代碼僅打印指令執(zhí)行的地址和長度信息。 實(shí)際應(yīng)用中可配合capstone反匯編引擎玩一些更騷的操作。

UCHOOKCODE的callback中可以修改PC或EIP等寄存器來改變程序運(yùn)行流程。實(shí)際上,Unicorn調(diào)試器的單步調(diào)試就是以這個(gè)為基礎(chǔ)實(shí)現(xiàn)的。

Unidbg

Allows you to emulate an Android native library, and an experimental iOS emulation.

下載代碼: https://github.com/zhkl0228/unidbg/releases/tag/v0.9.3,使用IntelliJ IDEA打開工程即可。

運(yùn)行代碼: com/bytedance/frameworks/core/encrypt/TTEncrypt.java, 出現(xiàn)下面的信息說明運(yùn)行成功。

代碼分析

入口點(diǎn):

  1. public static void main(String[] args) throws Exception {

  2. TTEncrypt test = new TTEncrypt(true);


  3. byte[] data = test.ttEncrypt();

  4. Inspector.inspect(data, "ttEncrypt");


  5. ? ? test.destroy();

  6. }

第一步: 補(bǔ)環(huán)境 跟蹤TTEncrypt函數(shù),注釋寫的很清楚了,不做過多分析?;咎茁范际沁@個(gè)樣子。

  1. TTEncrypt(boolean logging) {

  2. this.logging = logging;


  3. ? ? ? ?emulator = AndroidEmulatorBuilder.for32Bit().setProcessName("com.qidian.dldl.official").build(); // 創(chuàng)建模擬器實(shí)例,要模擬32位或者64位,在這里區(qū)分

  4. final Memory memory = emulator.getMemory(); // 模擬器的內(nèi)存操作接口

  5. ? ? ? ?memory.setLibraryResolver(new AndroidResolver(23)); // 設(shè)置系統(tǒng)類庫解析


  6. ? ? ? ?vm = emulator.createDalvikVM(null); // 創(chuàng)建Android虛擬機(jī)

  7. ? ? ? ?vm.setVerbose(logging); // 設(shè)置是否打印Jni調(diào)用細(xì)節(jié)

  8. DalvikModule dm = vm.loadLibrary(new File("unidbg-android/src/test/resources/example_binaries/libttEncrypt.so"), false); // 加載libttEncrypt.so到unicorn虛擬內(nèi)存,加載成功以后會(huì)默認(rèn)調(diào)用init_array等函數(shù)

  9. ? ? ? ?dm.callJNI_OnLoad(emulator); // 手動(dòng)執(zhí)行JNI_OnLoad函數(shù)

  10. ? ? ? ?module = dm.getModule(); // 加載好的libttEncrypt.so對(duì)應(yīng)為一個(gè)模塊


  11. TTEncryptUtils = vm.resolveClass("com/bytedance/frameworks/core/encrypt/TTEncryptUtils");

  12. }

第二步: HOOK相關(guān)的函數(shù) 跟蹤ttEncrypt,可知代碼hook了ssencrypt和ssencrypted_size兩個(gè)函數(shù)。

  1. byte[] ttEncrypt() {

  2. if (logging) {

  3. Symbol sbox0 = module.findSymbolByName("sbox0"); // 在libttEncrypt.so模塊中查找sbox0導(dǎo)出符號(hào)

  4. Symbol sbox1 = module.findSymbolByName("sbox1");

  5. Inspector.inspect(sbox0.createPointer(emulator).getByteArray(0, 256), "sbox0"); // 打印sbox0導(dǎo)出符號(hào)在unicorn中的內(nèi)存數(shù)據(jù)

  6. Inspector.inspect(sbox1.createPointer(emulator).getByteArray(0, 256), "sbox1");


  7. IHookZz hookZz = HookZz.getInstance(emulator); // 加載HookZz,支持inline hook,文檔看https://github.com/jmpews/HookZz

  8. ? ? ? ? ? ?hookZz.enable_arm_arm64_b_branch(); // 測(cè)試enable_arm_arm64_b_branch,可有可無

  9. ? ? ? ? ? ?hookZz.wrap(module.findSymbolByName("ss_encrypt"), new WrapCallback<RegisterContext>() { // inline wrap導(dǎo)出函數(shù)

  10. @Override

  11. public void preCall(Emulator<?> emulator, RegisterContext ctx, HookEntryInfo info) {

  12. Pointer pointer = ctx.getPointerArg(2);

  13. int length = ctx.getIntArg(3);

  14. byte[] key = pointer.getByteArray(0, length);

  15. Inspector.inspect(key, "ss_encrypt key");

  16. }

  17. @Override

  18. public void postCall(Emulator<?> emulator, RegisterContext ctx, HookEntryInfo info) {

  19. System.out.println("ss_encrypt.postCall R0=" + ctx.getLongArg(0));

  20. }

  21. });

  22. ? ? ? ? ? ?hookZz.disable_arm_arm64_b_branch();

  23. ? ? ? ? ? ?hookZz.instrument(module.base + 0x00000F5C + 1, new InstrumentCallback<Arm32RegisterContext>() {

  24. @Override

  25. public void dbiCall(Emulator<?> emulator, Arm32RegisterContext ctx, HookEntryInfo info) { // 通過base+offset inline wrap內(nèi)部函數(shù),在IDA看到為sub_xxx那些

  26. System.out.println("R3=" + ctx.getLongArg(3) + ", R10=0x" + Long.toHexString(ctx.getR10Long()));

  27. }

  28. });


  29. Dobby dobby = Dobby.getInstance(emulator);

  30. ? ? ? ? ? ?dobby.replace(module.findSymbolByName("ss_encrypted_size"), new ReplaceCallback() { // 使用Dobby inline hook導(dǎo)出函數(shù)

  31. @Override

  32. public HookStatus onCall(Emulator<?> emulator, HookContext context, long originFunction) {

  33. System.out.println("ss_encrypted_size.onCall arg0=" + context.getIntArg(0) + ", originFunction=0x" + Long.toHexString(originFunction));

  34. return HookStatus.RET(emulator, originFunction);

  35. }

  36. @Override

  37. public void postCall(Emulator<?> emulator, HookContext context) {

  38. System.out.println("ss_encrypted_size.postCall ret=" + context.getIntArg(0));

  39. }

  40. }, true);


  41. IxHook xHook = XHookImpl.getInstance(emulator); // 加載xHook,支持Import hook,文檔看https://github.com/iqiyi/xHook

  42. ? ? ? ? ? ?xHook.register("libttEncrypt.so", "strlen", new ReplaceCallback() { // hook libttEncrypt.so的導(dǎo)入函數(shù)strlen

  43. @Override

  44. public HookStatus onCall(Emulator<?> emulator, HookContext context, long originFunction) {

  45. Pointer pointer = context.getPointerArg(0);

  46. String str = pointer.getString(0);

  47. System.out.println("strlen=" + str);

  48. ? ? ? ? ? ? ? ? ? ?context.push(str);

  49. return HookStatus.RET(emulator, originFunction);

  50. }

  51. @Override

  52. public void postCall(Emulator<?> emulator, HookContext context) {

  53. System.out.println("strlen=" + context.pop() + ", ret=" + context.getIntArg(0));

  54. }

  55. }, true);

  56. ? ? ? ? ? ?xHook.register("libttEncrypt.so", "memmove", new ReplaceCallback() {

  57. @Override

  58. public HookStatus onCall(Emulator<?> emulator, long originFunction) {

  59. RegisterContext context = emulator.getContext();

  60. Pointer dest = context.getPointerArg(0);

  61. Pointer src = context.getPointerArg(1);

  62. int length = context.getIntArg(2);

  63. Inspector.inspect(src.getByteArray(0, length), "memmove dest=" + dest);

  64. return HookStatus.RET(emulator, originFunction);

  65. }

  66. });

  67. ? ? ? ? ? ?xHook.register("libttEncrypt.so", "memcpy", new ReplaceCallback() {

  68. @Override

  69. public HookStatus onCall(Emulator<?> emulator, long originFunction) {

  70. RegisterContext context = emulator.getContext();

  71. Pointer dest = context.getPointerArg(0);

  72. Pointer src = context.getPointerArg(1);

  73. int length = context.getIntArg(2);

  74. Inspector.inspect(src.getByteArray(0, length), "memcpy dest=" + dest);

  75. return HookStatus.RET(emulator, originFunction);

  76. }

  77. });

  78. ? ? ? ? ? ?xHook.refresh(); // 使Import hook生效

  79. }

第三步: 添加調(diào)試及主動(dòng)調(diào)用

  1. if (logging) {

  2. Debugger debugger = emulator.attach(DebuggerType.ANDROID_SERVER_V7); // 附加IDA android_server,可輸入c命令取消附加繼續(xù)運(yùn)行

  3. }

  4. byte[] data = new byte[16];

  5. ByteArray array = TTEncryptUtils.callStaticJniMethodObject(emulator, "ttEncrypt([BI)[B", new ByteArray(vm, data), data.length); // 執(zhí)行Jni方法

  6. return array.getValue();

  7. }

第四步: 銷毀環(huán)境

跟蹤destroy

  1. void destroy() throws IOException {

  2. ? ? ?emulator.close();

  3. if (logging) {

  4. System.out.println("destroy");

  5. }

  6. }

運(yùn)行結(jié)果

這個(gè)時(shí)候按c,繼續(xù),可以看到hook的結(jié)果以及JNI調(diào)用細(xì)節(jié)。

單步調(diào)試

ida_server的Debug方式相對(duì)簡單,對(duì)于unidbg的強(qiáng)大之一在于它的單步調(diào)試-- Console Debugger

寫在最后

作者的例子是以抖音作為例子的,還是很不錯(cuò)的。注釋都寫的比較清楚了。unidbg單步調(diào)試做的很棒,這個(gè)彌補(bǔ)了frida調(diào)試能力比較弱的缺點(diǎn)。

公眾號(hào)

更多內(nèi)容,歡迎關(guān)注我的微信公眾號(hào): 無情劍客。


Unidbg調(diào)試so的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國家法律
姚安县| 壶关县| 紫阳县| 康马县| 孝昌县| 大冶市| 柏乡县| 和政县| 怀宁县| 建瓯市| 城市| 延边| 图木舒克市| 电白县| 通许县| 安福县| 辉南县| 海门市| 太谷县| 丹寨县| 曲阜市| 清水河县| 峨山| 呼图壁县| 泌阳县| 邢台县| 凤凰县| 历史| 尤溪县| 壤塘县| 林甸县| 从江县| 海林市| 会东县| 孟村| 卓尼县| 临安市| 雅江县| 道真| 通山县| 兴文县|