Armv7汇编逆向:3D打印机加密Zip文件密码获取求助
3D打印机固件加密Zip密码定位与代码分析
问题背景
首次发帖,之前通过谷歌搜索从本站获取过不少实用技巧。现在正在分析一款3D打印机固件,目标是找出其加密Zip文件的密码,但完全没接触过汇编,分析起来很吃力。找到两段和图像显示相关的代码,推测和加密归档中的图像提取有关,但不知道怎么从这里追踪到解密逻辑和密码位置。
代码功能分析
1. _ZN16LanderBuildModel24yo_printer_build_a_layerEiPcii 函数
这段代码是3D打印层构建的核心流程,主要做这些事:
- 开头的栈帧操作(
push {fp, lr}、add fp, sp, #4等)是ARM汇编的标准函数入口,用来保存上下文和分配栈空间。 - 调用
printf打印日志(从bl ee30 <printf@plt>可以看出)。 - 调用
yo_display_image显示当前层的图像(对应代码里的bl 927bc <yo_display_image>)。 - 计算平台上升的微步距离(通过
smull、asr等指令做定点数运算),然后调用yo_printer_platform_move_up_micro控制平台上升。 - 调用
usleep/sleep做延时,通过yo_gpio_set控制外设引脚电平,完成打印层的固化等待流程。 - 最后清理栈帧,返回0。
对应的汇编代码:
000311b8 <_ZN16LanderBuildModel24yo_printer_build_a_layerEiPcii>: 311b8: e92d4800 push {fp, lr} 311bc: e28db004 add fp, sp, #4 311c0: e24dd010 sub sp, sp, #16 311c4: e50b0008 str r0, [fp, #-8] 311c8: e50b100c str r1, [fp, #-12] 311cc: e50b2010 str r2, [fp, #-16] 311d0: e50b3014 str r3, [fp, #-20] @ 0xffffffec 311d4: e59f00a0 ldr r0, [pc, #160] @ 3127c <_ZN16LanderBuildModel24yo_printer_build_a_layerEiPcii+0xc4> 311d8: e59f10a0 ldr r1, [pc, #160] @ 31280 <_ZN16LanderBuildModel24yo_printer_build_a_layerEiPcii+0xc8> 311dc: e59f209c ldr r2, [pc, #156] @ 31280 <_ZN16LanderBuildModel24yo_printer_build_a_layerEiPcii+0xc8> 311e0: ebff7712 bl ee30 <printf@plt> 311e4: e51b0010 ldr r0, [fp, #-16] 311e8: eb018573 bl 927bc <yo_display_image> 311ec: e51b3014 ldr r3, [fp, #-20] @ 0xffffffec 311f0: e59f208c ldr r2, [pc, #140] @ 31284 <_ZN16LanderBuildModel24yo_printer_build_a_layerEiPcii+0xcc> 311f4: e0c21293 smull r1, r2, r3, r2 311f8: e1a020c2 asr r2, r2, #1 311fc: e1a03fc3 asr r3, r3, #31 31200: e0633002 rsb r3, r3, r2 31204: e51b0008 ldr r0, [fp, #-8] 31208: e3a01000 mov r1, #0 3120c: e1a02003 mov r2, r3 31210: ebfffdfd bl 30a0c <_ZN16LanderBuildModel33yo_printer_platform_move_up_microEii> 31214: e59f006c ldr r0, [pc, #108] @ 31288 <_ZN16LanderBuildModel24yo_printer_build_a_layerEiPcii+0xd0> 31218: ebff78e1 bl f5a4 <usleep@plt> 3121c: e59f0068 ldr r0, [pc, #104] @ 3128c <_ZN16LanderBuildModel24yo_printer_build_a_layerEiPcii+0xd4> 31220: e3a01001 mov r1, #1 31224: eb0187ae bl 930e4 <yo_gpio_set> 31228: e51b300c ldr r3, [fp, #-12] 3122c: e3530001 cmp r3, #1 31230: ca000001 bgt 3123c <_ZN16LanderBuildModel24yo_printer_build_a_layerEiPcii+0x84> 31234: e3a0003c mov r0, #60 @ 0x3c 31238: ebff786d bl f3f4 <sleep@plt> 3123c: e59b2004 ldr r2, [fp, #4] 31240: e1a03002 mov r3, r2 31244: e1a03283 lsl r3, r3, #5 31248: e0623003 rsb r3, r2, r3 3124c: e1a03103 lsl r3, r3, #2 31250: e0833002 add r3, r3, r2 31254: e1a03183 lsl r3, r3, #3 31258: e1a00003 mov r0, r3 3125c: ebff78d0 bl f5a4 <usleep@plt> 31260: e59f0024 ldr r0, [pc, #36] @ 3128c <_ZN16LanderBuildModel24yo_printer_build_a_layerEiPcii+0xd4> 31264: e3a01000 mov r1, #0 31268: eb01879d bl 930e4 <yo_gpio_set> 3126c: e3a03000 mov r3, #0 31270: e1a00003 mov r0, r3 31274: e24bd004 sub sp, fp, #4 31278: e8bd8800 pop {fp, pc} 3127c: 00104070 .word 0x00104070 31280: 0010973c .word 0x0010973c 31284: 66666667 .word 0x66666667 31288: 00061a80 .word 0x00061a80 3128c: 0001001c .word 0x0001001c
2. yo_display_image 函数
这是图像显示的具体实现,依赖SDL库完成渲染:
- 先检查是否有已加载的SDL表面(Surface),如果有就调用
SDL_FreeSurface释放资源。 - 调用
yo_display_tool_load_image_to_surface加载图像到SDL表面(这是关键的图像入口,加密归档的图像提取逻辑大概率在这个函数里)。 - 将加载的表面保存到全局变量(
str r2, [r3],r3指向0x00168638这个全局地址)。 - 调用
yo_display_tool_apply_surface_to_surface将图像表面绘制到显示缓冲区。 - 调用
SDL_Flip刷新显示,完成图像输出。
对应的汇编代码:
000927bc <yo_display_image>: 927bc: e92d4800 push {fp, lr} 927c0: e28db004 add fp, sp, #4 927c4: e24dd010 sub sp, sp, #16 927c8: e50b0010 str r0, [fp, #-16] 927cc: e3a03000 mov r3, #0 927d0: e50b3008 str r3, [fp, #-8] 927d4: e59f3070 ldr r3, [pc, #112] @ 9284c <yo_display_image+0x90> 927d8: e5933000 ldr r3, [r3] 927dc: e3530000 cmp r3, #0 927e0: 0a000003 beq 927f4 <yo_display_image+0x38> 927e4: e59f3060 ldr r3, [pc, #96] @ 9284c <yo_display_image+0x90> 927e8: e5933000 ldr r3, [r3] 927ec: e1a00003 mov r0, r3 927f0: ebfdf257 bl f154 <SDL_FreeSurface@plt> 927f4: e24b3008 sub r3, fp, #8 927f8: e51b0010 ldr r0, [fp, #-16] 927fc: e1a01003 mov r1, r3 92800: ebffff5f bl 92584 <yo_display_tool_load_image_to_surface> 92804: e1a02000 mov r2, r0 92808: e59f303c ldr r3, [pc, #60] @ 9284c <yo_display_image+0x90> 9280c: e5832000 str r2, [r3] 92810: e59f3034 ldr r3, [pc, #52] @ 9284c <yo_display_image+0x90> 92814: e5932000 ldr r2, [r3] 92818: e59f302c ldr r3, [pc, #44] @ 9284c <yo_display_image+0x90> 9281c: e5933004 ldr r3, [r3, #4] 92820: e3a00000 mov r0, #0 92824: e3a01000 mov r1, #0 92828: ebffff72 bl 925f8 <yo_display_tool_apply_surface_to_surface> 9282c: e59f3018 ldr r3, [pc, #24] @ 9284c <yo_display_image+0x90> 92830: e5933004 ldr r3, [r3, #4] 92834: e1a00003 mov r0, r3 92838: ebfdf0c5 bl eb54 <SDL_Flip@plt> 9283c: e51b3008 ldr r3, [fp, #-8] 92840: e1a00003 mov r0, r3 92844: e24bd004 sub sp, fp, #4 92848: e8bd8800 pop {fp, pc} 9284c: 00168638 .word 0x00168638
定位解密代码与密码的步骤
- 追踪图像加载的上游逻辑:直接分析
yo_display_tool_load_image_to_surface函数,它的入参是图像标识,内部肯定会读取加密归档、解密图像。重点看它调用的文件操作、解密相关函数。 - 搜索Zip相关特征:在固件里搜索字符串
"PK"(Zip文件魔数)、"password"、"unzip"等关键词,找到解密入口;汇编层面找调用unzip类函数的指令,或CRC32、AES相关运算逻辑。 - 定位硬编码密码:在固件二进制里搜索ASCII字符串,重点找长度4-16位、类似密码的内容(比如厂商缩写、版本号);如果密码是加密存储的,找解密函数附近的常量字节数组。
- 动态调试(若可行):用调试器(如JTAG)连接打印机,在
yo_display_tool_load_image_to_surface处下断点,追踪读取的文件路径、解密函数及传递的密码参数;或模拟固件运行环境,捕获解密时的内存数据获取密码。
内容的提问来源于stack exchange,提问作者Jan Tchórzewski
相关产品推荐
相关产品推荐

