计算CALL偏移量

时间:2017-11-01 13:26:28

标签: c# assembly memory ollydbg

我试图通过创建一个字节数组,分配内存,写入分配的内存,然后创建远程线程来调用C#中的进程函数。据我所知,这是通过流程执行shellcode的常用方法。

          void WalkFunc()
    {
        byte[] asm = new byte[]
        {
            0x6A, 0x01, //PUSH 1
            0x31, 0xC9, //XOR ECX, ECX
            0xBA, 0x10, 0x00, 0x10, 0x00, //MOV EDX,00+10+00+10
            0xA1, 0xB0, 0x01, 0x83, 0x00, //MOV EAX,DWORD PTR DS:[8301B0]
            0xE8, 0x??, 0x??, 0x??, 0x??, //CALL 0x005378E4
            0xC3 //RETN
        };

        Process proc = Process.GetProcessesByName("process")[0];
        IntPtr hHandle = OpenProcess((int)ProcessAccessFlags.All, false, proc.Id);

        IntPtr hAlloc = VirtualAllocEx(hHandle, IntPtr.Zero, (uint)asm.Length, AllocationType.Commit, MemoryProtection.ExecuteReadWrite);

        UIntPtr bytesWritten = UIntPtr.Zero;

        WriteProcessMemory(hHandle, hAlloc, asm, (uint) asm.Length, out bytesWritten);

        uint iThreadId = 0;

        IntPtr hThread = CreateRemoteThread(hHandle, IntPtr.Zero, 0, hAlloc, IntPtr.Zero, 0, out iThreadId);

    }

如您所见,我无法找到呼叫偏移。实际上,在读完信息之后,我得到了那个没有静态偏移的呼叫,所以我必须计算跳转地址,如果我没错,那就是CALL。 在我的意见中,我的 TO是0x005378E4 。但我不知道如何找到 FROM 知道

  

VirtualAllocEx正在分配一个我无法在运行时预测的地址。

由于

1 个答案:

答案 0 :(得分:0)

直接call uses a rel32 displacement from the end of the call instruction.

您知道asm[]的地址,因为您已经分配了它。  (它不是编译时常量,因为您正在使用动态分配,因此您必须使用从new获得的指针。)

您标记了此[C++]指针数学很容易。只需转换为intptr_t并减去得到2的补码整数(因为此代码仅在x86上编译时才有效,所以你可以假设),并检查它是否足够小以适应之前施放到int32_t。将其存储到数组中。 (您可能希望将其定义为打包struct,或者只使用memcpy。)

但您的代码是[c#]。 IDK如何将原始指针值作为整数获取。 It's apparently possible with unsafe。如果您可以静态分配块,那可能会更容易;您可以让链接器在链接时执行重定位以达到给定的绝对地址。 (除非您需要生成重定位,因此将您的"数据"放在单独的.asm文件中会更容易。您仍然可以将其放入读写数据部分,而不是代码,但您可以使用asm助记符编写代码,让汇编程序为绝对call目标生成重定位。

您可以在寄存器或内存中使用绝对目标地址的间接跳转。如果事实证明你的内存块距你的目标超过2GB(在64位模式下),那么这也是必需的。

您可以这样做只是为了使您的代码与位置无关,因此在找到它加载的位置后不需要修复它。

; don't forget to save/restore esi around this
mov   esi, 0x005378E4       ; pick any reg the callee won't look at.  save/restore if necessary
call  esi

或者如果你不能打扰寄存器

push   0x005378E4       ; before pushing args so the callee sees the same stack/
push   1
call   [esp+4]

32位模式确实有call ptr16:32直接电话,但不要使用它,因为您必须知道正确的cs段描述符到硬编码。 (即现在的)。它也很慢,甚至不能在64位模式下使用,所以只是不要。

相关问题