读取程序集 x86 IA-32 中的文件



我正在尝试读取汇编(x86,IA-32)中的文件,我发现了这个例子:

mov ebx,eax
mov al,0x3
mov edi,esp
mov ecx,edi
xor edx,edx
mov dh,0xff
mov dl,0xff
int 0x80

在 EAX(第一条指令)中,有打开系统调用的返回代码。
有两件事我没有完全理解:

  1. 为什么先做mov edi,esp然后mov ecx,edi而不是直接做mov ecx,esp
  2. 为什么要将0xff0xff放入EDX寄存器中?读取系统调用需要count因此在这种情况下文件大小。

编辑(完整代码):

section .text
global _start
_start:
;read the file
jmp short call_rw
rw:
push 0x5
pop eax
pop ebx
xor ecx,ecx
int 0x80
mov ebx,eax
mov al,0x3
mov edi,esp
mov ecx,edi
xor edx,edx
mov dl,0xff
mov dh,0xff
int 0x80
mov edx,eax
push 0x4
pop eax
mov bl, 0x1
int 0x80
push 0x1
pop eax
inc ebx
int 0x80
call_rw:
call rw
message db "/home/user/file.txt"

对于你的第一个问题,我可以看到几个相当明显的可能性,但这个问题没有足够的信息来确定哪个可能是准确的。

第一种可能性是,edi中的大小稍后在代码中用于其他目的,因此移动到edi已经完成了一些有用的事情,但我们在这里看不到确切的内容,因为我们看不到使用它的其他代码。

另一种明显的可能性是,这只是一个错误。

有一些不太明显的可能性,例如mov ecx, edi被用作其他代码的入口点,因此,如果您从此代码的开头开始,它将使用esp中的值,但是还有其他代码将其他一些值加载到edi然后跳转到mov ecx, edi, 因此使用不同的值而不是esp中的值。

还有一些其他的可能性,例如有人基本上插入了一些NOP的等效物,以(例如)使代码的某些部分与某个边界对齐,但没有那么多的分心行,就好像他们写了NOP(比如)5次一样。

对于您的第二个问题,0xffffedx基本上意味着它将从文件中读取多达 65535 字节。他们很可能分配了一个 65535 字节的缓冲区,因此他们不想在一次调用中读取更多内容。

编辑(将完整代码添加到问题后)。好的,现在我们可以看到完整的代码,我们可以从代码(尽可能好)非常非常规地编写的事实开始1.

他首先跳到call_rw,然后(显然足够)从那里callrw。这会在call_rw立即将地址推送到堆栈上。然后在rw,他将堆栈中的返回值弹出到ebx。这会将message的地址加载到ebx中,然后在下一次系统调用中将其用作参数(函数 5,打开一个文件,期望ebx包含指向文件名的指针)。

顺便说一句,我几乎不得不猜测代码要么是故意的(但相当无效的)混淆尝试,要么是编译器在内部生成某种面向堆栈的内部代码的结果,然后做了一个非常糟糕的工作将其转换为面向寄存器的目标代码。或者也许我的第一印象(见下面的脚注)是正确的。

去除皮屑后,前几个系统调用会按照这个一般顺序进行

; open the file
mov eax, 5
mov ebx, offset filename
xor ecx, ecx
int 0x80
; read the file
mov ebx, eax
mov eax, 3
mov ecx, esp
mov edx, 0xffff
int 0x80

对不起,但我懒得整理其余的。乍一看,它看起来像进入了一个无限循环(call_rw之前的代码流入call_rw,再次调用rw)。它的一些体操可能会阻止这种情况真正发生,但没有令人信服的论据来证明这样做的必要性,我缺乏整理更多这种特殊混乱的动力。


  1. 在这里非常努力地做外交工作。在修订之前,这称作者为"可证明的精神病患者"。

相关内容

最新更新