首页
社区
课程
招聘
30
[原创]某二次元开放世界冒险游戏反作弊分析报告
发表于: 2025-2-14 12:13 12548

[原创]某二次元开放世界冒险游戏反作弊分析报告

2025-2-14 12:13
12548

好久没碰某二次元开放世界冒险游戏了,听说新升级了反作弊,故来一探究竟,并尝试实现一些简单的功能。

这种级别的游戏首先不考虑静态分析,直接跑起来。不出意外肯定不能直接内存读写,想附加调试器也是附加不上的,所以选择先从驱动入手,游戏加载时会加载驱动。

先尝试简单的拦截,方法很多:注册 LoadImage 回调拦截,改驱动名等等等。后者比较好实现,但是运行游戏一段时间会弹窗强制退出。

而如果说让保护加载,自己起一个句柄提权的驱动,则会被弹窗退出。

尝试过在虚拟机里直接启动游戏,不出意外也是弹窗。

使用启动时注入的方式,手动 Create 进程挂起,再远线程注入,可以将 DLL 注入,因为游戏刚运行的时候是没有驱动保护的,自然可以获得正常的游戏句柄。

DLL 直接用 imgui 做 hook 就行,网上框架巨多,先浅浅尝试一下改锁帧的功能,由于这个游戏锁 60 帧,因此玩的很难受,尝试找一下这个值。

反复修改反复找可以找到四个值,地址较小的那个是真实值

imgui里面直接用这个值绑定滑动条,实现帧率解锁。

面临的难点主要是反调试和反虚拟机。

先说结论:R3程序使用了多种类型的反虚拟机技术,大部分通过hook api 的形式可以直接过掉。

Hook CreateFileWCreateFileA 这两个 API,可以看出在尝试打开如下的设备和文件

不用想,游戏打开这些文件肯定是在检测虚拟机,这里将文件添加到一个 set 中,每次打开遍历一遍,遇到它检测的文件就直接返回无效句柄。

只需要对 yxxxshen.exemxxxbase.dll 两个模块做 IAT hook 即可。下面是拦截成功的一些日志,实际上还有更多的设备,这里不一一展示:

运行过程中会有一段调用了进程遍历的关键函数 Process32NextW,应该是检测虚拟机的相关进程,这里直接匹配当前虚拟机存在的一些虚拟机特有的进程不让它返回即可。

如果找到 vm 相关进程则持续调用,直到进程名不包含 vm 或者为 VGAuthService 即可。下面是一些拦截成功的日志:

游戏调用了 NtOpenDirectoryObjectNtQueryDirectoryObject 两个 API,经过测试发现它打开了 \Device 路径,也就是开始遍历了驱动对象。

这两个 api 可以先hook打印,但是单纯绕过检测 hook 后者即可。

这里也给出一些拦截成功的日志

注意到 mxxxbase.dll 的一个函数

GetTickCount64 获取系统启动以来经过的毫秒数。

它做了 10 次测试,每次测试 10000 条 cpuid 指令运行所需的时间,在虚拟机里,它很大,物理机中几乎每次都为 0。

那么便可以:

强制将两次运行的 cpuid 的时间设为一致。

下面是日志

可以对比得到,hook 前和 hook 后的差距大概是有几十毫秒的,这里会被检测到,通常物理机的间隔都是 0。

该函数调用了,但是没进行检测,提前写好以免后面加这个检测,检测的方式通常是检查 MAC 地址前三字节的信息看厂商是否为 Vmware 之类的。

hook 注册表相关的 api,拦截对应 open 的 key 的名字,实际上也是有调用没检测。

这里输出了一些相关log

但是预计可能是两个一起检测的,即:注册表判断服务是否存在,再判断驱动文件是否存在,有一样不成立就不认为检测到了虚拟机。

过完这些虚拟机检测之后,也是成功可以在虚拟机中启动 yxxxshen.exe 了。

R3的反调试相对比较简单,除了众所周知的 IsDebuggerPresent 之外,早期的版本似乎 hookDbgBreakPointDbgUiRemoteBreakin 两个 API 来防止调试器附加,现在仍有 hook,不过只 hookDbgBreak,并且同样也有 ThreadHideFromDebugger 检测。

NtSetInformationThread 这个 API 本意是设置线程优先级的,其中有一个参数 ThreadInformationClass,这是一个 THREADINFOCLASS 的枚举类型。

其中注意到 0x11 即为 ThreadHideFromDebugger,字面意思也不难理解,就是从调试器中隐藏该线程,据看雪一篇文章的分析,该函数关于 ThreadHideFromDebugger 的实现如下

可以看出当 classThreadHideFromDebugger 时,若 ThreadInformationLength 不为 0 则返回一个错误。因此过这个反调试不能无脑拦截 classThreadHideFromDebugger 的调用,而应注意这里的 Length 是否为 0。根据拦截 yxxxshen.exe 的调用可以看出。

它连续调用了两次,第一次估计设置 Length 为 1,看是否调用失败,第二次才是真正的反调试,因此需要辨别出这一点。

似乎也不难写出它的 hook 函数?

但是很不幸的是,你会得到一个闪退。

思路似乎中断了,于是考虑看看与之相近的 API,也就是 NtQueryInformationThread

可以看到在前后各成功调用一次 NtQueryInformationThread,并且将 class 设为了 ThreadHideFromDebugger

这不对吧,query 它能干什么呢,对了,查询信息,可能是需要查询跟隐藏线程调试器相关的字段,那么会不会是因为成功 set 了和没成功 set 了情况不太一样呢?

这里 hook 掉看看前后查询的数据的区别。

这里我保留关键的 LOG,也可以看出来,它在 set 前后分别查询了一次,第一次查询得知的结果是 0,而成功调用 set 之后得到的结果会是 1,如果仅仅 hook set 不让它调用则会在第二次查询也得到 0 的结果,这便是之前闪退的原因了。

因此对于这个反调试,需要同时 hook NtQueryInformationThreadNtSetInformationThread,严格判断参数,并合理过滤掉一些检测反调试和反-反-反调试的东西。

这个已经被玩烂了的 API 相信是第一个被考虑到的,hook它永远返回 0 就行了。

可以在虚拟机中,附加调试器的情况下运行该二次元开放世界冒险游戏且不报错。

主要尝试分析检测逻辑,尽可能地在不影响功能的情况下过掉检测。

先给结论:反调试主要由驱动创建的一个线程实现,入口点在 0x2f0c0,重复顺序执行以下逻辑:

下面给出笔者的分析步骤和对应的解决方案。

R0 层的反调试其实反而没那么难,因为 API 就那么几个,HxxxKProtect.sys 的反调试具体表现为,在双机调试的情况下成功加载之后会导致调试器无响应。

根R0调试相关的API找一下即可,通过 IDA 直接搜索导入表或者字符串,得到以下几个跟调试器相关的

根据查阅 MSDN 可知,这两个是内核中的标志位,尝试 hook 将它修改到其它位置。运行之后发现调试器依旧被剥离,但是虚拟机似乎也卡死,并没有蓝屏,在游戏终端中发现了上传日志。

路径中可以看到上传了由于驱动导致的蓝屏(dmp),和自己的信息文件。

info.txt 包含了操作系统的信息,硬件信息和uid信息。

这些信息大概率都是注册表或者一个 API GetSystemFirmwareTable 读出来的,这里为了防止被上传,最好把注册表处理干净,所有跟 Vmware 相关的全部替换掉。

其它特征去除直接用大表哥的 vmloader(大表哥nb),不知道这里怎么访问这两个标志的,所以先尝试 Hook MmGetSystemRoutineAddress,再去导入表替换两个标志位。

创建一个线程,持续输出两个标志位

附加调试器的情况下,输出应当是 1 0

加载游戏之后,会发现标志位变为了 0 1,而 KdDebuggerEnabled 标志位一旦被复位,windbg 会直接被剥离,因此需要阻止。

这里本想尝试加载驱动后,设置硬件断点在 KdDebuggerEnabled 字符串和对应的标志位中,但是似乎会有检测,如果设置了硬断驱动则会加载失败。

通过动调,还是找到了关键的指令。

这一步 RCX 读取了自身驱动导入表的那个指针,存到了 r11 指向的内存

经过多次调试,最终确定写入的指令为

如下所示(本次调试截图与上面截图不是同一次调试)

这里再次确认一下:

第一点很好判断,直接软件断点走过来,观察这条指令前后标志位的变化,从下图来看,基本可以确认了,虽然 KdDebuggerEnabled 和 RAX 指向的地址不同,但是它们一定是映射了同一个物理页。

第二点经过确认,至少第一次触发该指令就是用于修改这个标志位的,把这个指令 Patch 掉之后,会被蓝屏,蓝屏模块为 kdcom.dll,蓝屏代码为 IRQL_NOT_LESS_OR_EQUAL

毫无疑问,调试出问题了,看起来内核调试不仅仅是靠这一个标志位决定的(之前一直不知道)。于是想着去分析一下官方的 API,来看看剥离内核调试器需要做什么样的步骤。分析了一会发现想的都是错的,应该是用了一些我们平时想不到的操作去做的。

也是此时,猛然回首,感觉自己可能正往错误的方向行进,vmp 调起来太累,又不会还原。这时候想到了模拟执行,在队里师傅的帮助下,找到 KACE 这个模拟执行的工具,但是编译什么的都很有问题,且需要自己装 zydis 库,而最新的版本又没适配最新的 zydis,甚至很多结构都改变了,遂尝试自己修一下,下面给出我修好的版本 https://github.com/xia0ji233/KACE。

模拟执行最关键的一点就是驱动要能独立加载,比如能直接使用 monitor 或者 sc 这种简单的工具加载,很不幸这个二次元开放世界冒险游戏并不能。分析其 R3 的行为,发现游戏运行的时候会往注册表写下一个 ConfigData,加载驱动之后会立刻删除,由于中间延时还挺高,所以可以捕获这一过程。

分析这串数据时间成本过高,所以可以选择,先运行 yxxxshen.exe,等到写上去之后再马上运行模拟器,就可以成功在模拟器中跑起来

下面分析 DriverEntry 的执行步骤。

直到这里,模拟执行已经跑不出什么更加细节的东西了,转动态调试。

调试器中手动 rdmsr 拿到返回的地址下硬件读断点,截取到驱动的读取操作,驱动拿到了 MSR 返回的 syscall 地址之后,先判断了该地址是否合法,再尝试读取其中的四字节数,并且有一个循环,循环每次加1,从图中可以清晰看到。

随后将拿到的四字节整数进行了 &0x00F0FFFF 的操作,最后和 0x00108D4C 判断是否相等,转小端序来看,它需要找到类似这样的特征码 4C 8D 1? ??,这里不管直接在条件满足的分支下断点,在 jne 下方下断点再过来看看它找到了什么位置。

也就是说拿到了 KiSystemServiceRepeat 的地址,通过搜索找到了一篇文章,里面提到了通过 MSR 寻找得到未导出的 KeServiceDescriptorTableKeServiceDescriptorTableShadow,文章里面使用了特征偏移的方法寻找这两个表,当然不同的系统版本这个值必然也不同,因此该驱动使用了兼容性更好的特征 KiSystemServiceRepeat 函数头的方式去寻找这个偏移,拿到对应的两个表的地址。

随后必然读了两个表,之前模拟执行也得到过该结论

下两个硬件断点发现仅仅是判断了一下两张表的表头内容是否一致

然后读走了熟悉的 0x1d8(表中系统服务的数量)。

随后调用了 MmIsAddressValid,在模拟器中可以看到,模拟调用了一个0,因为模拟器的局限性,不太可能还原真实的内核情况,那来看看实际上它取的 0 来自哪里。

FFFFF8052FCC79F0,也就是 SSDT 存的 KiServiceTable,也许很大概率是发现 SSDT 存的 KiServiceTable 为 0 了,所以模拟器加载驱动才会失败。

在模拟器中简单实现这两个结构之后,驱动就照着走后续加载的逻辑

通过模拟器打印对应的指令去trace,最终在驱动文件找到了对应的调用函数,幸运的是这个函数没被v,看一下大致逻辑

其中,sub_140029100 是它封装的打开文件的函数。这里的调用链路也很符合模拟器跑的结果,既然没 v,那就直接拦截,断点,调试一气呵成。

最终发现对以下 8 个文件进行了打开操作。

并且获取了它们的完整名称,后续进行的操作都 v 了,不过看后面有类似验 hash 的操作,感觉可能是检查这些进程的签名,如果是白签名那么不限制获取游戏的句柄。

(以上分析皆来自 5.2 版本,后续分析使用了 5.3 版本)

随后使用模拟器跑

无非就是注册回调,创建线程,后续主线程退出,因为没有写 wdf 对应的框架的 API,所以模拟器里面不会正确返回 0,但是DriverEntry 的逻辑确实是跑完了。可见反调试并不在 DriverEntry 当中,应该在创建的线程中,创建线程的地址在 +0x2f0c0 的地址上,这个地址虽然是 .text 段,但是 v 了,不太好静态分析,选择模拟器分析。

直接把 DriverEntry 设置为线程入口点试试看跑的结果,关键反调试的 Log 如下:

在四处地方都有读取调试标志位的操作,计算得到偏移如下

模拟器中没跑出写 KdDebuggerEnabled 的操作,大概率因为在模拟器中该标志为0才不会执行写的操作,这里在读的 case 这里判断一下将 KdDebuggerEnabled 读取的数值修改为 1。

执行结果如下:

得到写入 KdDebuggerEnabled 的指令偏移为 0x281d20

将它改为 mov r11d, [r9] 指令,再来看看会不会被剥离调试器,经测试发现 kdcom 还是蓝屏,那么尝试在读取的指令入手,经测试,0x371b7a 若读到了 1 则会写,因此尝试把这里的

改为 xor dx,dx,同理改掉四个读取的位置,让它们读的值分别为未调试状态读取的值,但是会导致虚拟机被卡死,同时调试器也是未响应的状态,似乎没什么思路了,于是再次考虑动态调试。

因为当时会蓝屏,所以修改系统设置获取完整的 Memory.dmp,一通分析发现 data 段被清零了。

最后通过动态调试发现了一个神秘的函数

看到这个函数基本可以验证刚才的猜想了,那就直接把这个函数覆盖 0xC3,观察是否蓝屏。

发现已经完全不会蓝屏,调试器也可以正常工作,那就意味着后面可以正常调试游戏驱动保护了。

尝试分析这个函数,研究它是怎么干掉调试器的。

通过 ZwQuerySystemInformation 获取 kdcom.dll 的基址和模块大小。

随后通过解析 PE 文件找到 .data 段的基址和大小。

随后获取到该段的物理地址,使用 MDL 映射该内存(虽然+0x39240函数被 v 了,但可以合理怀疑这个函数就是申请 MDL 使用的,后续通过动态调试也能得到这个结论)。

进入这个 memset 函数,可以发现将 kdcom.dllmagic 清零之后 kdcom 工作将不正常,其中 fffff8033e455000 为模块本身的虚拟内存,RCX 指向了 MDL 分配的虚拟内存,此时汇编代码通过 RCX 写入 0,在现在这种情况下,单步调试会导致调试器直接断开。

绕过的思路也很简单,抹 PE 头是最简单粗暴 & 安全的方式,因为在获取 NT 头的时候会进行 magic 判断,判断不成功自然不会去搞 kdcom 了。

但是都 inline hook 了那么多,再多这一个又有什么所谓呢

不是,这这这这是是是是谁把 C3 放到我游戏驱动的反调试函数头了,这这这是谁不成心……

嗯,一定是太阳黑子射到了内存,把它改成C3了,总不能是一个黑签名驱动调用了 PsSetLoadImageNotifyRoutine 注册了加载模块回调,然后识别 HxxxYOKProtect.sys 再用 MDL 把这个内存给改了吧。

注册了如下回调

yxxxshen 以前是有主动的句柄降权的,但是这个版本测试下来没有开,只能等开了再分析,并且其它回调通过 hook 和模拟执行等手段并没有发现做了什么操作。

不管是直接拦还是 ARK 工具看都很方便,这里还是选择hook,拿到句柄之后直接取消这个回调,看看 CE 能否直接读写内存。

用 ARK 工具可以看到,这里驱动正常加载,且正常注册了进程/线程创建回调和模块加载回调,去特征 CE 不加载 DBK 可直接读取游戏内存,且驱动不会降权句柄。

再来具体分析一下降了哪些权限,虽然回调函数被 v 了,但是不妨碍可以做 hook,只要比较一下打开 PROCESS_ALL_ACCESS 的游戏句柄,看看最终得到的权限就行了,这里选择hook注册回调的函数,在注册回调的时候拦截,注册上自己的回调,自己的回调再调用真正的回调函数即可。

自己写的驱动记得加 bypass check sign,不然会返回 0xC0000022

最终打开游戏进程得到以下 LOG

跟宏定义比对一下。

可以发现降了如下的权限:

没研究出这个回调干了什么,一般情况下应该是会拦截一些黑工具的使用的,比如 CE 和 xdbg 之类的,没想到没拦,为了保证安全把回调直接取消了也可以。

同样也是注册了但是貌似并没有使用,经测试,只把句柄回调去掉之后可以直接远线程注入游戏

感谢 @Qfrost@上学困难户 在分析过程中提供技术支持,本篇报告发布的时候,游戏已经升级到 5.4 版本。

\\.\vmmemctl
C:\Windows\system32\DRIVERS\vm3dmp.sys
C:\Windows\system32\drivers\vm3dmp_loader.sys
...
\\.\vmmemctl
C:\Windows\system32\DRIVERS\vm3dmp.sys
C:\Windows\system32\drivers\vm3dmp_loader.sys
...
HANDLE gh_CreateFileW(...) {
    for (auto it : DeviceFileBlacklist) {
        if (CaseInsensitiveContains(lpFileName, it)) {
            DBG_PRINT("black device \"%ws\" not allowed to open\n", lpFileName);
            return INVALID_HANDLE_VALUE;
        }
    }
    HANDLE hFile = CreateFileW(...);
    bool flag = true;
    for(auto it:FileBlacklist){
        if (CaseInsensitiveContains(lpFileName,it)) {
            flag = false;
            break;
        }
    }
    DBG_PRINT("CreateFileW called with %ws return value %p\n", lpFileName, hFile);
    return hFile;
}
HANDLE gh_CreateFileW(...) {
    for (auto it : DeviceFileBlacklist) {
        if (CaseInsensitiveContains(lpFileName, it)) {
            DBG_PRINT("black device \"%ws\" not allowed to open\n", lpFileName);
            return INVALID_HANDLE_VALUE;
        }
    }
    HANDLE hFile = CreateFileW(...);
    bool flag = true;
    for(auto it:FileBlacklist){
        if (CaseInsensitiveContains(lpFileName,it)) {
            flag = false;
            break;
        }
    }
    DBG_PRINT("CreateFileW called with %ws return value %p\n", lpFileName, hFile);
    return hFile;
}
[Debug Info]black device "\\.\vmmemctl" not allowed to open
[Debug Info]black device "C:\Windows\system32\DRIVERS\vm3dmp.sys" not allowed to open
[Debug Info]black device "C:\Windows\system32\drivers\vm3dmp_loader.sys" not allowed to open
...
[Debug Info]black device "\\.\vmmemctl" not allowed to open
[Debug Info]black device "C:\Windows\system32\DRIVERS\vm3dmp.sys" not allowed to open
[Debug Info]black device "C:\Windows\system32\drivers\vm3dmp_loader.sys" not allowed to open
...
BOOL gh_ProcessNextW(HANDLE hSnapshot, LPPROCESSENTRY32W lppe) {
    BOOL ret = Process32NextW(hSnapshot, lppe);
    WCHAR *szExeFile = lppe->szExeFile;
    while (CaseInsensitiveContains(szExeFile, L"vm")||CaseInsensitiveContains(szExeFile,L"VGAuthService") && ret) {
        DBG_PRINT("Found Vm in Process name %ws,try to execute again\n", szExeFile);
        ret = Process32NextW(hSnapshot, lppe);
        szExeFile = lppe->szExeFile;
        DBG_PRINT("new Process Name %ws pid=%d ret=%d\n", lppe->szExeFile, lppe->th32ProcessID, ret);
    }
    DBG_PRINT("ProcessNextW called with %ws pid=%d ret=%d\n", lppe->szExeFile,lppe->th32ProcessID ,ret);
    return ret;
}
BOOL gh_ProcessNextW(HANDLE hSnapshot, LPPROCESSENTRY32W lppe) {
    BOOL ret = Process32NextW(hSnapshot, lppe);
    WCHAR *szExeFile = lppe->szExeFile;
    while (CaseInsensitiveContains(szExeFile, L"vm")||CaseInsensitiveContains(szExeFile,L"VGAuthService") && ret) {
        DBG_PRINT("Found Vm in Process name %ws,try to execute again\n", szExeFile);
        ret = Process32NextW(hSnapshot, lppe);
        szExeFile = lppe->szExeFile;
        DBG_PRINT("new Process Name %ws pid=%d ret=%d\n", lppe->szExeFile, lppe->th32ProcessID, ret);
    }
    DBG_PRINT("ProcessNextW called with %ws pid=%d ret=%d\n", lppe->szExeFile,lppe->th32ProcessID ,ret);
    return ret;
}
[Debug Info]Found Vm in Process name vm3dservice.exe,try to execute again
[Debug Info]new Process Name vmtoolsd.exe pid=3916 ret=1
[Debug Info]Found Vm in Process name vmtoolsd.exe,try to execute again
[Debug Info]new Process Name svchost.exe pid=3928 ret=1
[Debug Info]ProcessNextW called with svchost.exe pid=3928 ret=1
[Debug Info]Found Vm in Process name vm3dservice.exe,try to execute again
[Debug Info]new Process Name vmtoolsd.exe pid=3916 ret=1
[Debug Info]Found Vm in Process name vmtoolsd.exe,try to execute again
[Debug Info]new Process Name svchost.exe pid=3928 ret=1
[Debug Info]ProcessNextW called with svchost.exe pid=3928 ret=1
NTSTATUS gh_NtQueryDirectoryObject(...) {
    auto ret = NtQueryDirectoryObject(...);
    auto info = (POBJECT_DIRECTORY_INFORMATION)Buffer;
    for(auto it:DeviceBlackList){
        if(CaseInsensitiveEqual(info->Name.Buffer,it)){
            DBG_PRINT("NtQueryDirectoryObject name=\"%wZ\" return %d Deny to open!\n",
            info->Name, info->TypeName, ret);
            info->Name = DeniedDevice;
            return 0;
        }
    }
    DBG_PRINT("NtQueryDirectoryObject name=\"%wZ\",Type=\"%wZ\" return %d\n",
    info->Name, info->TypeName, ret);
    return ret;
}
NTSTATUS gh_NtQueryDirectoryObject(...) {
    auto ret = NtQueryDirectoryObject(...);
    auto info = (POBJECT_DIRECTORY_INFORMATION)Buffer;
    for(auto it:DeviceBlackList){
        if(CaseInsensitiveEqual(info->Name.Buffer,it)){
            DBG_PRINT("NtQueryDirectoryObject name=\"%wZ\" return %d Deny to open!\n",
            info->Name, info->TypeName, ret);
            info->Name = DeniedDevice;
            return 0;
        }
    }
    DBG_PRINT("NtQueryDirectoryObject name=\"%wZ\",Type=\"%wZ\" return %d\n",
    info->Name, info->TypeName, ret);
    return ret;
}
[Debug Info]NtQueryDirectoryObject name="gpuenergydrv",Type="Device" return 0
[Debug Info]NtQueryDirectoryObject name="VMCIHostDev" return 697297488 Deny to open!
[Debug Info]NtQueryDirectoryObject name="00000068",Type="Device" return 0
[Debug Info]NtQueryDirectoryObject name="gpuenergydrv",Type="Device" return 0
[Debug Info]NtQueryDirectoryObject name="VMCIHostDev" return 697297488 Deny to open!
[Debug Info]NtQueryDirectoryObject name="00000068",Type="Device" return 0
ULONGLONG st=40000;
 
ULONGLONG gh_GetTickCount64() {
    auto ret = GetTickCount64();
    if (st == 0) {
        DBG_PRINT("GetTickCount64 called %lld\n", ret);
        st = ret;
    }
    else {
        DBG_PRINT("GetTickCount64 called change %lld to %lld\n", ret, st);
        ret = st;
        st = 0;
    }
    return ret;
}
ULONGLONG st=40000;
 
ULONGLONG gh_GetTickCount64() {
    auto ret = GetTickCount64();
    if (st == 0) {
        DBG_PRINT("GetTickCount64 called %lld\n", ret);
        st = ret;
    }
    else {
        DBG_PRINT("GetTickCount64 called change %lld to %lld\n", ret, st);
        ret = st;
        st = 0;
    }
    return ret;
}
[Debug Info]GetTickCount64 called 4117687
[Debug Info]GetTickCount64 called change 4117718 to 4117687
[Debug Info]GetTickCount64 called 4117734
[Debug Info]GetTickCount64 called change 4117812 to 4117734
[Debug Info]GetTickCount64 called 4117687
[Debug Info]GetTickCount64 called change 4117718 to 4117687
[Debug Info]GetTickCount64 called 4117734
[Debug Info]GetTickCount64 called change 4117812 to 4117734
ULONG gh_GetAdaptersInfo(...) {
    auto ret = GetAdaptersInfo(AdapterInfo, SizePointer);
    DBG_PRINT("GetAdaptersInfo called with %p %p return %d\n",...);
    //换成intel的MAC地址60:45:2E
    AdapterInfo->Address[0] = 0x60;
    AdapterInfo->Address[1] = 0x45;
    AdapterInfo->Address[2] = 0x2E;
    return ret;
}
ULONG gh_GetAdaptersInfo(...) {
    auto ret = GetAdaptersInfo(AdapterInfo, SizePointer);
    DBG_PRINT("GetAdaptersInfo called with %p %p return %d\n",...);
    //换成intel的MAC地址60:45:2E
    AdapterInfo->Address[0] = 0x60;
    AdapterInfo->Address[1] = 0x45;
    AdapterInfo->Address[2] = 0x2E;
    return ret;
}
[Debug Info]RegOpenKeyExA called with FFFFFFFF80000002 "SYSTEM\CurrentControlSet\services\vm3dmp_loader" 0 131353 000000702B0FF5B0 return 0
[Debug Info]CreateFileW called with C:\Program Files (x86)\mihoyo\games\Genshin Impact Game\yuanshen_Data\Persistent\base_res_version_hash return value 0000000000000CDC
[Debug Info]black device "C:\Windows\system32\drivers\vm3dmp_loader.sys" not allowed to open
[Debug Info]RegOpenKeyExA called with FFFFFFFF80000002 "SYSTEM\CurrentControlSet\services\vm3dmp_loader" 0 131353 000000702B0FF5B0 return 0
[Debug Info]CreateFileW called with C:\Program Files (x86)\mihoyo\games\Genshin Impact Game\yuanshen_Data\Persistent\base_res_version_hash return value 0000000000000CDC
[Debug Info]black device "C:\Windows\system32\drivers\vm3dmp_loader.sys" not allowed to open
typedef enum _THREADINFOCLASS {
    ThreadBasicInformation          = 0,
    //...
    ThreadPriorityBoost             = 14,
    ThreadSetTlsArrayAddress        = 15,   // Obsolete
    ThreadIsIoPending               = 16,
    ThreadHideFromDebugger          = 17,
     //...
    MaxThreadInfoClass              = 51,
} THREADINFOCLASS;
typedef enum _THREADINFOCLASS {
    ThreadBasicInformation          = 0,
    //...
    ThreadPriorityBoost             = 14,
    ThreadSetTlsArrayAddress        = 15,   // Obsolete
    ThreadIsIoPending               = 16,
    ThreadHideFromDebugger          = 17,
     //...
    MaxThreadInfoClass              = 51,
} THREADINFOCLASS;
case ThreadHideFromDebugger:
    if (ThreadInformationLength != 0) {
        return STATUS_INFO_LENGTH_MISMATCH;
    }
    st = ObReferenceObjectByHandle (...);
    if (!NT_SUCCESS (st)) {
        return st;
    }
    PS_SET_BITS (&Thread->CrossThreadFlags, PS_CROSS_THREAD_FLAGS_HIDEFROMDBG);
    ObDereferenceObject (Thread);
    return st;
    break;
case ThreadHideFromDebugger:
    if (ThreadInformationLength != 0) {
        return STATUS_INFO_LENGTH_MISMATCH;
    }
    st = ObReferenceObjectByHandle (...);
    if (!NT_SUCCESS (st)) {
        return st;
    }
    PS_SET_BITS (&Thread->CrossThreadFlags, PS_CROSS_THREAD_FLAGS_HIDEFROMDBG);
    ObDereferenceObject (Thread);
    return st;
    break;
[Debug Info]NtSetInformationThread called with handle fffffffe 17 at ... length 1 return c0000004
[Debug Info]NtSetInformationThread called with handle fffffffe 17 at ... length 0 return 0
[Debug Info]NtSetInformationThread called with handle fffffffe 17 at ... length 1 return c0000004
[Debug Info]NtSetInformationThread called with handle fffffffe 17 at ... length 0 return 0
UINT64 gh_NtSetInformationThread(...) {
    if(ThreadInformationClass==0x11 && ThreadInformationLength==0){
        DBG_PRINT("Try to set ThreadHideFromDebugger,Stop it\n");
        return 0;
    }
    auto ret = NtSetInformationThread(...);
    DBG_PRINT("lasterror=%d\n", GetLastError());
    DBG_PRINT("NtSetInformationThread called with handle %x %d at %p length %d return %x\n",...);
    return ret;
}
UINT64 gh_NtSetInformationThread(...) {
    if(ThreadInformationClass==0x11 && ThreadInformationLength==0){
        DBG_PRINT("Try to set ThreadHideFromDebugger,Stop it\n");
        return 0;
    }
    auto ret = NtSetInformationThread(...);
    DBG_PRINT("lasterror=%d\n", GetLastError());
    DBG_PRINT("NtSetInformationThread called with handle %x %d at %p length %d return %x\n",...);
    return ret;
}
[Debug Info]NtQueryInformationThread called with handle fffffffe 17 at ... length 4 return c0000004
[Debug Info]NtQueryInformationThread called with handle fffffffe 17 at ... length 1 return 0
[Debug Info]NtSetInformationThread called with handle fffffffe 17 at ... length 1 return c0000004
[Debug Info]NtSetInformationThread called with handle fffffffe 17 at ... length 0 return 0
[Debug Info]NtQueryInformationThread called with handle fffffffe 17 at ... length 4 return c0000004
[Debug Info]NtQueryInformationThread called with handle fffffffe 17 at ... length 1 return 0
[Debug Info]NtQueryInformationThread called with handle fffffffe 17 at ... length 4 return c0000004
[Debug Info]NtQueryInformationThread called with handle fffffffe 17 at ... length 1 return 0
[Debug Info]NtSetInformationThread called with handle fffffffe 17 at ... length 1 return c0000004
[Debug Info]NtSetInformationThread called with handle fffffffe 17 at ... length 0 return 0
[Debug Info]NtQueryInformationThread called with handle fffffffe 17 at ... length 4 return c0000004
[Debug Info]NtQueryInformationThread called with handle fffffffe 17 at ... length 1 return 0
[Debug Info]past information=34
[Debug Info]after information=00
[Debug Info]NtQueryInformationThread called with handle fffffffe 17 at ... length 1 return 0
[Debug Info]NtSetInformationThread called with handle fffffffe 17 at ... length 0 return 0
[Debug Info]past information=95
[Debug Info]after information=01
[Debug Info]NtQueryInformationThread called with handle fffffffe 17 at ... length 1 return 0
[Debug Info]past information=34
[Debug Info]after information=00
[Debug Info]NtQueryInformationThread called with handle fffffffe 17 at ... length 1 return 0
[Debug Info]NtSetInformationThread called with handle fffffffe 17 at ... length 0 return 0
[Debug Info]past information=95
[Debug Info]after information=01

[招生]科锐逆向工程师培训(2025年3月11日实地,远程教学同时开班, 第52期)!

最后于 2025-2-14 12:17 被xi@0ji233编辑 ,原因:
收藏
免费 30
支持
分享
赞赏记录
参与人
雪币
留言
时间
mb_vzsnpfhs
+1
谢谢你的细致分析,受益匪浅!
1天前
艾米哈柏
感谢你的积极参与,期待更多精彩内容!
2025-3-10 12:47
thexin7
感谢你的积极参与,期待更多精彩内容!
2025-3-6 14:35
mb_shzsxtje
+6
感谢你分享这么好的资源!
2025-3-6 13:40
kishou_yusa
为你点赞!
2025-2-26 11:00
老小白
非常支持你的观点!
2025-2-25 10:41
mb_vjjsrsbp
你的帖子非常有用,感谢分享!
2025-2-24 13:36
powerpcer
这个讨论对我很有帮助,谢谢!
2025-2-24 07:32
mb_ytalqmdq
+1
你的分享对大家帮助很大,非常感谢!
2025-2-21 12:00
3zureus
你的分享对大家帮助很大,非常感谢!
2025-2-20 10:58
mb_sedplcgt
你的帖子非常有用,感谢分享!
2025-2-19 23:57
vyang2024
+1
你的帖子非常有用,感谢分享!
2025-2-19 23:05
hjf571x
+1
期待更多优质内容的分享,论坛有你更精彩!
2025-2-19 17:04
七夜大大
你的帖子非常有用,感谢分享!
2025-2-19 17:03
wuxiwudi
你的分享对大家帮助很大,非常感谢!
2025-2-19 14:02
PeterZheng
为你点赞!
2025-2-19 10:21
lracker
+2
为你点赞!
2025-2-18 22:44
ufufjvjvj
感谢你的积极参与,期待更多精彩内容!
2025-2-17 23:01
xiangyandt
+1
这个讨论对我很有帮助,谢谢!
2025-2-17 10:48
ifyou
你的帖子非常有用,感谢分享!
2025-2-17 10:07
Amun
+1
这个讨论对我很有帮助,谢谢!
2025-2-17 09:59
木志本柯
+5
你的帖子非常有用,感谢分享!
2025-2-16 17:21
chengdrgon
谢谢你的细致分析,受益匪浅!
2025-2-16 12:39
TubituX
+1
感谢你的贡献,论坛因你而更加精彩!
2025-2-16 01:21
P_Hac
+1
你的帖子非常有用,感谢分享!
2025-2-15 18:01
hahayzl
谢谢你的细致分析,受益匪浅!
2025-2-14 22:28
kekao
+1
这个讨论对我很有帮助,谢谢!
2025-2-14 22:25
moshuiD
谢谢你的细致分析,受益匪浅!
2025-2-14 19:35
令狐双
感谢你的贡献,论坛因你而更加精彩!
2025-2-14 16:02
Kvancy
+5
谢谢你的细致分析,受益匪浅!
2025-2-14 14:34
打赏 + 100.00雪花
打赏次数 1 雪花 + 100.00
收起 
赞赏  mb_rsjnrjwy   +100.00 2025/03/02 感谢分享~
最新回复 (14)
雪    币: 1036
活跃值: (1521)
能力值: ( LV9,RANK:404 )
在线值:
发帖
回帖
粉丝
2

是二次元黑客!

2025-2-14 12:21
0
雪    币: 1352
活跃值: (2462)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
3
精彩
2025-2-14 14:00
0
雪    币: 715
活跃值: (674)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
4
Hacker!!!
2025-2-14 14:29
0
雪    币: 1270
活跃值: (1241)
能力值: ( LV3,RANK:36 )
在线值:
发帖
回帖
粉丝
5
太厉害了师傅,向师傅学习!
2025-2-14 19:35
0
雪    币: 1865
活跃值: (1605)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
6
我去,是二次元黑客!
2025-2-14 20:23
0
雪    币: 3378
活跃值: (2296)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
MYGA
2025-2-14 21:26
0
雪    币: 9688
活跃值: (6925)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
8
原神启动!
2025-2-15 04:14
0
雪    币: 1434
活跃值: (1699)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
9
启动!
2025-2-15 16:13
0
雪    币: 4974
活跃值: (4950)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
666很棒的对抗过程,货真驾驶的逆向分析过程。
2025-2-16 17:21
0
雪    币: 3002
活跃值: (3466)
能力值: ( LV8,RANK:147 )
在线值:
发帖
回帖
粉丝
11
mark
2025-2-19 10:37
0
雪    币: 863
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
12
崇拜的眼神投来,跪拜
2025-2-19 17:05
0
雪    币: 6313
活跃值: (1081)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
13
感谢分享
2025-2-19 20:49
0
雪    币: 20
活跃值: (1064)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
你简直是牛逼给牛逼开门牛逼到家了
2025-2-24 05:07
0
雪    币: 39
活跃值: (484)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
mark
2025-3-2 11:49
0
游客
登录 | 注册 方可回帖
返回

账号登录
验证码登录

忘记密码?
没有账号?立即免费注册