| 初赛 这题与18年的题目的一部分相似。 
 典型的自由视角解锁问题,常见于各类FPS游戏。 
 过程: 
 首先通过IDA静态分析,发现其为OpenGL做的3维图形显示程序 
 从网上找到了比较类似的代码: 
 
 执行程序后发现了箭头,但是没有发现另一副图画,这引起了我的注意 
 发现其实移动鼠标是有视野的,但是并没有全面,所以直接联想到FPS游戏中的视角解锁,之前做过D3D游戏的视角解锁挂(没错就是吃鸡),但是没有接触过OpenGL 
 其实原理都是一样的 
 这里有篇好文章 
 
 这里简要说一下, 
2021腾讯游戏安全技术竞赛PC客户端初赛writeup   这里从内存中加载了两幅图,最后是OpenGL绘图 
 进去之后OpenGL对照源码标记函数,这个没啥好讲的 
2021腾讯游戏安全技术竞赛PC客户端初赛writeup   我们想解锁自由视角,就需要控制camera 
 核心函数就是 
2021腾讯游戏安全技术竞赛PC客户端初赛writeup   
2021腾讯游戏安全技术竞赛PC客户端初赛writeup   剩下的就是祭出Detour大法,InlineHook函数,替换 
 那两个 glm::mat4 坐标为自己设定的值,就能解锁视角 
2021腾讯游戏安全技术竞赛PC客户端初赛writeup   很简单,设定好Hook点,同时我们获取了程序glfwGetKey的函数地址,做了键盘的视角控制函数 
2021腾讯游戏安全技术竞赛PC客户端初赛writeup   WSAD控制着摄像机的坐标,RT为缩放 
 之后我们使用DetourCreateProcessWithDll来让DLL注入到进程中,其实最开始用DetourSetDll程序设置程序import注入Dll,结果发生了黑屏图片显示不正常的问题,这个是因为修改了文件头,破坏了最初的拿图片数据的结构,所以只能动态去注入Hook 
2021腾讯游戏安全技术竞赛PC客户端初赛writeup   使用Detours的DetourCreateProcessWithDll函数将Dll注入到程序中实现Hook 
 通过WSAD和RT控制镜头,得到对应的flag:dogod // DllMain
#include "stdafx.h"
 
#define RVA_glfwGetKey 0x19920
 
#define RVA_Get_p_windows_HookPoint 0x06542
#define RVA_Key_HookPoint 0x06BDB
#define RVA_Setprojection_HookPoint 0x06CDB
#define RVA_SetView_HookPoint 0x06DEE
 
glm::vec3 cameraPos = glm::vec3(0.0f, 0.0f, 3.0f);
glm::vec3 cameraFront = glm::vec3(0.0f, 0.0f, -1.0f);
glm::vec3 cameraUp = glm::vec3(0.0f, 1.0f, 0.0f);
 
float fov = 50.0f;
 
typedef DWORD(__cdecl* pfnglfwGetKey)(DWORD p_windows, DWORD KeyValue);
pfnglfwGetKey m_glfwGetKey;
 
DWORD p_windows;
HMODULE hModule_EXE;
PVOID p_windows_HookPoint = NULL;
PVOID p_GetKey_HookPoint = NULL;
 
PVOID p_Setprojection = NULL;
PVOID p_Setview = NULL;
 
glm::mat4 projection;
glm::mat4 view;
 
VOID NAKED Get_p_windows()
{
    STACK_FRAME_BEGIN
        __asm {
        mov p_windows, eax
    }
    STACK_FRAME_END
        __asm {
        push p_windows_HookPoint
        ret
    }
 
}
 
VOID NAKED prcessInPut()
{
    STACK_FRAME_BEGIN
        if (m_glfwGetKey(p_windows, GLFW_KEY_W) == GLFW_PRESS)
        {
            cameraPos += cameraFront;
        }
    if (m_glfwGetKey(p_windows, GLFW_KEY_S) == GLFW_PRESS)
    {
        cameraPos -= cameraFront;
    }
    if (m_glfwGetKey(p_windows, GLFW_KEY_A) == GLFW_PRESS)
    {
        cameraPos -= glm::normalize(glm::cross(cameraFront, cameraUp));
    }
    if (m_glfwGetKey(p_windows, GLFW_KEY_D) == GLFW_PRESS)
    {
        cameraPos += glm::normalize(glm::cross(cameraFront, cameraUp));
    }
    if (m_glfwGetKey(p_windows, GLFW_KEY_R) == GLFW_PRESS)
    {
        fov -= 1.0;
    }
    if (m_glfwGetKey(p_windows, GLFW_KEY_T) == GLFW_PRESS)
    {
        fov += 1.0f;
 
    }
    view = glm::lookAt(cameraPos, cameraFront + cameraPos, cameraUp);
    projection = glm::perspective(glm::radians(fov), (float)800.0 / (float)600.0, 0.1f, 200.0f);
 
    STACK_FRAME_END
        __asm {
        push p_GetKey_HookPoint
        ret
    }
}
 
VOID NAKED Setprojection()
{
    __asm {
        mov ecx, offset projection
        push p_Setprojection
        ret
    }
}
 
VOID NAKED Setview()
{
    __asm
    {
        mov ecx, offset view
        push p_Setview
        ret
    }
}
 
BOOL DetourHook()
{
    if (DetourTransactionBegin() == NO_ERROR)
    {
        DetourAttach(&p_windows_HookPoint, Get_p_windows);
        DetourAttach(&p_GetKey_HookPoint, prcessInPut);
        DetourAttach(&p_Setprojection, Setprojection);
        DetourAttach(&p_Setview, Setview);
 
        if (DetourTransactionCommit() == NO_ERROR)
        {
            return TRUE;
        }
    }
    return FALSE;
}
 
BOOL APIENTRY DllMain(HMODULE hModule,
    DWORD  ul_reason_for_call,
    LPVOID lpReserved
)
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        hModule_EXE = GetModuleHandle(NULL);
        m_glfwGetKey = (pfnglfwGetKey)((DWORD)hModule_EXE + RVA_glfwGetKey);
 
        p_windows_HookPoint = (PVOID)((DWORD)hModule_EXE + RVA_Get_p_windows_HookPoint);
        p_GetKey_HookPoint = (PVOID)((DWORD)hModule_EXE + RVA_Key_HookPoint);
        p_Setprojection = (PVOID)((DWORD)hModule_EXE + RVA_Setprojection_HookPoint);
        p_Setview = (PVOID)((DWORD)hModule_EXE + RVA_SetView_HookPoint);
 
        DetourHook();
        break;
    case DLL_THREAD_ATTACH:
        break;
    case DLL_THREAD_DETACH:
        break;
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}
2021腾讯游戏安全技术竞赛PC客户端初赛writeup   在这里我偷懒了,发现只通过控制镜头的pos和缩放就能看到flag,实际中还有通过鼠标控制镜头朝向,大致的原理都一样。 
 
 
 |