Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如果编辑线程的指令指针,如何跳回(旧的)指令指针?_C#_Assembly_64 Bit_Pinvoke_X86 64 - Fatal编程技术网

C# 如果编辑线程的指令指针,如何跳回(旧的)指令指针?

C# 如果编辑线程的指令指针,如何跳回(旧的)指令指针?,c#,assembly,64-bit,pinvoke,x86-64,C#,Assembly,64 Bit,Pinvoke,X86 64,我试图编辑一个线程的指令指针,让它在跳回到旧的指令指针之前调用一些组装好的x64程序集,并按照正常方式继续。在我恢复线程后,我正在执行此操作的程序崩溃,我假设该线程指示它没有跳回旧的指令指针 目前,我正在尝试以下方法 获取线程的句柄 [DllImport("kernel32.dll", SetLastError = true)] public static extern IntPtr OpenThread(ThreadPrivileges dwDesiredAccess, bool bInher

我试图编辑一个线程的指令指针,让它在跳回到旧的指令指针之前调用一些组装好的x64程序集,并按照正常方式继续。在我恢复线程后,我正在执行此操作的程序崩溃,我假设该线程指示它没有跳回旧的指令指针

目前,我正在尝试以下方法

获取线程的句柄

[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr OpenThread(ThreadPrivileges dwDesiredAccess, bool bInheritHandle, IntPtr dwThreadId);

public enum ThreadPrivileges
{
    SuspendResume = 0x02,
    GetContext = 0x08,
    SetContext = 0x010,
    AllAccess = SuspendResume | GetContext | SetContext
}

var threadId = Process.GetProcessesByName(processName)[0].Threads[0].Id;

var threadHandle = OpenThread(ThreadPrivileges.AllAccess, false, (IntPtr)threadId);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern void SuspendThread(IntPtr hThread);

SuspendThread(threadHandle); 
[DllImport("kernel32.dll", SetLastError = true)]
public static extern void ResumeThread(IntPtr hThread);

ResumeThread(threadHandle);
挂起线程

[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr OpenThread(ThreadPrivileges dwDesiredAccess, bool bInheritHandle, IntPtr dwThreadId);

public enum ThreadPrivileges
{
    SuspendResume = 0x02,
    GetContext = 0x08,
    SetContext = 0x010,
    AllAccess = SuspendResume | GetContext | SetContext
}

var threadId = Process.GetProcessesByName(processName)[0].Threads[0].Id;

var threadHandle = OpenThread(ThreadPrivileges.AllAccess, false, (IntPtr)threadId);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern void SuspendThread(IntPtr hThread);

SuspendThread(threadHandle); 
[DllImport("kernel32.dll", SetLastError = true)]
public static extern void ResumeThread(IntPtr hThread);

ResumeThread(threadHandle);
获取线程的上下文

[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr OpenThread(ThreadPrivileges dwDesiredAccess, bool bInheritHandle, IntPtr dwThreadId);

public enum ThreadPrivileges
{
    SuspendResume = 0x02,
    GetContext = 0x08,
    SetContext = 0x010,
    AllAccess = SuspendResume | GetContext | SetContext
}

var threadId = Process.GetProcessesByName(processName)[0].Threads[0].Id;

var threadHandle = OpenThread(ThreadPrivileges.AllAccess, false, (IntPtr)threadId);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern void SuspendThread(IntPtr hThread);

SuspendThread(threadHandle); 
[DllImport("kernel32.dll", SetLastError = true)]
public static extern void ResumeThread(IntPtr hThread);

ResumeThread(threadHandle);
可以在此处找到Context64和ContextFlags的结构

尝试将旧指令指针写入堆栈

[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, uint nSize, int lpNumberOfBytesWritten);

context.Rsp -= sizeof(ulong); // Allocate 8 bytes on the stack

WriteProcessMemory(processHandle, (IntPtr)context.Rsp, BitConverter.GetBytes(context.Rip), sizeof(ulong), 0);
覆盖指令指针

context.Rip = (ulong)myAssemblyPointer;
将线程上下文设置为编辑的上下文

[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool SetThreadContext(IntPtr hThread, ref Context64 lpContext);

SetThreadContext(threadHandle, ref context);
最后恢复线程

[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr OpenThread(ThreadPrivileges dwDesiredAccess, bool bInheritHandle, IntPtr dwThreadId);

public enum ThreadPrivileges
{
    SuspendResume = 0x02,
    GetContext = 0x08,
    SetContext = 0x010,
    AllAccess = SuspendResume | GetContext | SetContext
}

var threadId = Process.GetProcessesByName(processName)[0].Threads[0].Id;

var threadHandle = OpenThread(ThreadPrivileges.AllAccess, false, (IntPtr)threadId);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern void SuspendThread(IntPtr hThread);

SuspendThread(threadHandle); 
[DllImport("kernel32.dll", SetLastError = true)]
public static extern void ResumeThread(IntPtr hThread);

ResumeThread(threadHandle);
我不确定这是否有任何相关性,但我使用的程序集如下

PUSHFQ
PUSH rax
PUSH rbx
PUSH rcx
PUSH rdx
PUSH r8
PUSH r9
PUSH r10
PUSH r11

sub RSP, 0x28
movabs RCX, 0x0000000000000000  ; Pointer 1
movabs RAX, 0x0000000000000000  ; Pointer 2
call RAX
add RSP, 0x28

POP r11
POP r10
POP r9
POP r8
POP rdx
POP rcx
POP rbx
POP rax
POPFQ

ret
我试图尽可能多地排除代码(错误检查和之后清理),以保持本文的简短,但我所有的错误检查似乎都表明pinvoke方法正在按预期工作。我主要关心的是当我试图将旧的指令指针写入堆栈时。虽然
WriteProcessMemory
没有失败,但我感觉我做得不对。如果有人能向我解释我是否正确地编写了指向堆栈的旧指令指针,如果没有,我将如何完成它,我将不胜感激

如果您希望我提供任何其他信息,例如
processHandle
myAssemblyPointer
变量,请告知我。

根据注释:


您只读取了4个字节,需要读取8个字节,因为这是一个x64进程,这是内存地址指针所需的大小。long只有4个字节,您需要使用long-long。

我看到的唯一可能的问题是,您没有确保钩子函数的堆栈指针对齐。可能没关系。使用调试器查看崩溃的位置。
BitConverter.GetBytes(context.Rip)、sizeof(ulong)
-这对于x64也是错误的-您只写入4个字节的返回地址,而不是8个字节。当然,您需要将强制对齐rsp的asm代码更改为16字节。另外,您不需要获取
CONTEXT\u FULL
CONTEXT\u控件就足够了。和main-如果线程说wait in system call(通常是这种情况,也会发生),那么只有在线程退出wait状态后,代码才会执行,比如
push rbp mov rbp,rsp和rsp,而不是0Fh sub rsp,20h/**/mov rsp,rbp pop rbp
&context.Rip,sizeof(context.Rip)
他没有覆盖任何指令,就像修补二进制文件一样。他在堆栈上动态推送当前RIP,并强制将另一个值加载到RIP中。当他的thunk返回时,它应该返回到执行被中断的点。他还需要确保堆栈指针正确对齐,正如Jester所提到的。事实上,根据对被钩住进程的了解,RSP可能没有指向有效的堆栈空间。(这部分可能不值得担心。)