1, 出发点
LoongArch上拥有二进制翻译功能,通过LATX + wine的方式可以运行windows应用程序。因此其也受限于 LATX 和 wine 两款软件的实现完整度。实际上,在我看来,二进制翻译其实是一些x86指令进行了RISC化实现,用于x86指令一对一或者多对一转为LoongArch自身的指令。比如猜测x86的push类指令,从LoongArch公开的手册来看,需要使用addi.d减去sp,再用st.d去存储寄存器。可能存在二进制翻译的指令能够实现一条指令将寄存器压栈。又比如从大佬提到的eflags,非官方但全面的 LoongArch 常见问题解答,可以猜测出二进制翻译的指令可能会存在一些JCC指令,又或是在计算时能产生标志位,毕竟当前LoongArch几乎是未使用到标志寄存器的。当然,这仅仅是一种猜测,期待二进制翻译的手册早日开放。
2, 下载superpi
百度了一个地址,像这种软件应该遍地可以下吧super_pi_mod.zip
3, 脱壳
这个的由来是因为当我在运行时,(运行方法见大佬的帖子,包教包会:龙芯3A5000上尝试运行任意Windows软件),发现会报
"ir1_translate fail"' failed”
这样的错误,这显然时翻译出现了问题。这时候我就可以祭出winedbg这样的工具,这个工具是wine的一个调测工具,用法与gdb类似,但功能并不全面。(毕竟这已经算是在linux调试windows程序了,已经很满足了 😀 )。这时候我发现根本不好调试,断点都没办法下,毕竟是加壳了的。
尽管此处是题外话,但是也需要记录下来,如何得到一个仅仅脱壳了的但是未修改其他内容的文件。
查壳如下,UPX壳,使用ESP法则即可脱去。(相当于这是原程序是个压缩程序,把执行代码全压缩了,然后入口处就在解压。函数进入时修改了esp,退出时将再次修改回esp。)
入口很好找到,就在0x410000处。我所使用的OD dump太弱,不能直接dump,采用LordPE + Scylla 的方式进行dump。
使用LordPE时,0x401000 - 0x410000 处设置了保护,修改dump引擎可以解决。再进行完整转存即可。
Scylla的步骤大概如下,修复LordPE拿到的dumped.exe即可,生成的文件为dumped_SCY.exe。
拿到的文件可以在x86上运行即脱壳成功。
4, 断点寻找不能翻译的指令
经过测试,LoongArch上的winedbg功能很诡异,只能下一次断点,不能使用ni,si这样的单步指令。而且下多了断点,只会触发第一次的断点。不知道是为什么 😅 。
通过与x86的比较,一次次用b *某个地址,例如 b *0x410000。定位到是enter指令翻译出现问题。
5, 替换enter
因未翻译enter,因此需要修改enter。enter的命令类似于 push ebp; mov ebp,esp; sub esp,xx;
汇编语言ENTER和LEAVE指令:创建和结束堆栈帧
enter指令长度为4个字节,通常用的call是5个字节,enter指令后一般是函数的prologue,也就是说是push指令的可能性很大。可以设计先call到某个位置,执行完后再通过ret跳回。当然也可以使用jmp,执行完后jmp跳回,但是call应该比较省空间,毕竟需要在那些未执行到的代码上作修改,空间还是很有限的。代码应该类似于这样
pop eax
push ebp
mov ebp,esp
sub esp,xx
push yy
push eax
ret
将使用到10字节的空间。
经过不断查找,总结出以下位置是enter出现的地方(至少需要12个)。已经一些不会执行到的指令空间,0x41eec8 - 0x41ef28 (可以放9个) 0x41d192 - 0x41d2a7 (可以放27个, emmmm 🤣 )
enter地址,esp大小,后一条指令push,调用替换地址
0x422e43, 0x10, edi, 0x41d192
0x41ee54, 0x1c, edi, 0x41d19c
0x41ed76, 0x20,edi, 0x41d1a6
0x423406, 0x58,ebx, 0x41d1b0
0x41f10c, 0x10, ebx, 0x41d1ba
0x41e8b6, 0x14,ebx, 0x41d1c4
0x41e5b6, 0x8, edi, 0x41d1ce
0x423ae6, 0x4, edi, 0x41d1d8
0x41e7d8, 0x4,ebx, 0x41d1e2
0x41e71a, 0x14,ebx, 0x41d1ec
0x41e036, 0xc,edi, 0x41d1f6
0x41df70, 0x10,edi, 0x41d192
0x41dfda, 0x18,edi, 0x41d200
0x41e2f1, 0x4,edi, 0x41d1d8
0x41efc8, 0x8,edi, 0x41d1ce
0x41e3b0, 0x4,ebx, 0x41d1e2
6, 完结
至此,修改后的super_pi能在LoongArch机器上通过wine使用了,但是测得比较大时会凉凉,enmmm。不知道为什么,我用的superpi在虚拟机里面测32M也总是报错,无论是脱壳还是未脱壳,在物理机上并不会出现这个问题。
贴图看看分数,enmmm 😅 还得加油吧。
附件:super pi LoongArch 0414