吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 1103|回复: 7
收起左侧

[C&C++ 原创] 远程注入代码利用SetTimer函数实现异常处理

[复制链接]
king1027 发表于 2024-6-16 12:08
本帖最后由 king1027 于 2024-6-16 12:15 编辑

简介

windows默认会用异常处理程序包含SetTimer的回调函数TimerProc,所以可以利用这一点给远程注入代码加上异常处理过程,防止注入代码导致远程程序异常崩溃。并且异常处理过程由windows自动处理,不需要编写额外代码,非常方便。

微软文档所述:

Windows 会将其对 TimerProc 的 调用括起来,其中包含使用和放弃所有异常的异常处理程序。 这是自 Windows 2000 以来的默认行为,但在 Windows 的未来版本中,这一行为可能会更改。 https://learn.microsoft.com/zh-cn/windows/win32/api/winuser/nf-winuser-setuserobjectinformationw

验证SetTimer函数自带异常处理

首先必须知道的是由windows消息队列来调用TimerProc函数。具体的说是SetTimer函数带回调函数时,由DispatchMessage函数调用TimerProc函数,且触发异常后,异常以后的代码不会被执行。

新建VS工程,选windows控制台程序,完整代码如下。

#include <windows.h>
#include <iostream>

using namespace std;

// 计时器回调函数
VOID CALLBACK Timerproc(
  HWND hwnd,        // handle to window for timer messages 
  UINT message,     // WM_TIMER message 
  UINT idTimer,     // timer identifier 
  DWORD dwTime)     // current system time
{
  cout << "Timerproc" << endl;
  int a = 1, b = 0, c = 0;
  c = a / b;  // 这句代码会引发异常,除数为零
  cout << c << endl;
}

int main() {
  //const HWND hwnd = GetConsoleWindow(); // 获取本进程句柄

  const UINT_PTR timer_id = SetTimer(nullptr,      // 绑定的窗口句柄
                                     0,            // timer ID
                                     0x0,          // 倒计时数,毫秒
                                     Timerproc);   // 回调函数
  int Counter = 0;
  MSG msg;
  while (GetMessage(&msg, nullptr, 0, 0)) {
    ++Counter;
    cout << "Counter: " << Counter << "; message: " << msg.message << '\n';
    DispatchMessage(&msg);
  }
  return 0;
}

1.png

调试运行,VS输出标签里重复提示除数为零异常,但程序仍然正常运行,没有显示cout << c << endl;这句代码,说明异常处理程序确实包含了TimerProc函数。

新线程内执行TimerProc函数

控制台程序

远程注入的代码是通过CreateRemoteThread函数执行,也就是新建一个线程。所以先来模拟本地新线程执行情景。

#include <windows.h>
#include <iostream>
#include <process.h>

using namespace std;

HANDLE hEvent;
// 计时器回调函数
VOID CALLBACK Timerproc(
  HWND hwnd,        // handle to window for timer messages 
  UINT message,     // WM_TIMER message 
  UINT idTimer,     // timer identifier 
  DWORD dwTime)     // current system time
{
  cout << "Timerproc" << endl;
  KillTimer(hwnd, idTimer);
  int a = 1, b = 0, c = 0;
  c = a / b;  // 这句代码会引发异常,除数为零
  cout << c << endl;
  SetEvent(hEvent);
}

DWORD WINAPI thread(_In_ LPVOID lpParameter) {
  HWND process_hwnd = *(HWND*)lpParameter;
  cout << "process_hwnd=" << process_hwnd << endl;
  cout << "thread start PID=" << GetCurrentThreadId() << endl;
  UINT_PTR timer_id;
  const HANDLE thread_hwnd = GetCurrentThread();
  timer_id = SetTimer(nullptr, 0, 0, nullptr);
  timer_id = SetTimer(process_hwnd,      // 绑定的窗口句柄
                      timer_id,     // timer ID
                      0x0,          // 倒计时数,毫秒
                      Timerproc);   // 回调函数

  hEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);
  WaitForSingleObject(hEvent, 5000);
  cout << "WaitForSingleObject end" << endl;
  CloseHandle(hEvent);
  return 0;
}

int main() {
  //HANDLE process_handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId());
  //cout << "process_handle=" << process_handle << endl;

  HWND process_hwnd = GetConsoleWindow();
  cout << "process_hwnd=" << process_hwnd << endl;
  const HANDLE thread_handle = CreateThread(nullptr, 0, thread, &process_hwnd, 0, nullptr);
  cout << "CreateThread thread_handle=" << thread_handle << endl;
  BOOL bRet;
  int Counter = 0;
  MSG msg;
  while ((bRet = GetMessage(&msg, nullptr, 0, 0)) != 0) {
    if (bRet == -1) {
      // handle the error and possibly exit
    }
    else {
      ++Counter;
      cout << "Counter: " << Counter << "; message: " << msg.message << '\n';
      TranslateMessage(&msg);
      DispatchMessage(&msg);
    }

  }
  return 0;
}

上面的代码无法运行成功,原因是TimeProc函数并未执行。没有执行是因为消息队列没有消息,那么GetMessage就会阻塞进程,不执行while循环体。不进入循环体,DispatchMessage函数就无法调用TimeProc函数。

至于为什么这里SetTimer函数没有触发消息……我也不知道。

窗口程序

控制台程序无法成功运行,但是换窗口程序却可以成功运行。

代码流程:

  1. WinMain函数是主函数,主函数中创建新线程执行thread函数。
  2. thread函数中创建事件,新建空计时器。新建空计时器是为了避免覆盖注入进程中已有的计时器(当SetTimer函数的第1、2参数为0时,windows会自动在当前进程创建新的计时器ID)。然后再次设置计时器,传入注入进程句柄、新建空计时器ID、Timerproc回调函数。最后执行WaitForSingleObject函数阻塞等待事件信号,如果Timerproc函数触发异常了,则会超时指定时间后继续执行。
  3. Timerproc函数可以自动处理异常,需要注意的是触发异常后的代码不会被执行。函数首先关闭计时器,接着直接插入注入代码或调用call函数,最后设置信号为有状态,以便让WaitForSingleObject函数接收信号。
  4. call函数有没有都可以,单独的call函数方便编程和调试。

改进的代码如下:

#include <iostream>
#include <windows.h>

using namespace std;

static const TCHAR gc_szClassName[] = TEXT("Test");
static const TCHAR gc_szWindowTitle[] = TEXT("Test");

HANDLE hEvent;

void call() {
  int a = 1, b = 0, c = 0;
  c = a / b;  // 这句代码会引发异常,除数为零
  cout << c << endl;
}

// 计时器回调函数
VOID CALLBACK Timerproc(
  HWND hwnd,        // handle to window for timer messages 
  UINT message,     // WM_TIMER message 
  UINT idTimer,     // timer identifier 
  DWORD dwTime)     // current system time
{
  cout << "Timerproc" << endl;
  if (KillTimer(hwnd, idTimer))
    cout << "KillTimer done" << endl;
  else
    cout << "KillTimer error" << endl;
  call(); // 如果函数内异常导致退出,则不会执行下面的代码
  SetEvent(hEvent);
}

DWORD WINAPI thread(_In_ LPVOID lpParameter) {
  HWND process_hwnd = *(HWND*)lpParameter;
  cout << "process_hwnd=" << process_hwnd << endl;
  cout << "thread start PID=" << GetCurrentThreadId() << endl;
  UINT_PTR timer_id;
  const HANDLE thread_hwnd = GetCurrentThread();
  hEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);
  timer_id = SetTimer(nullptr, 0, 0, nullptr);
  timer_id = SetTimer(process_hwnd,      // 绑定的窗口句柄
                      timer_id,     // timer ID
                      0x0,          // 倒计时数,毫秒
                      Timerproc);   // 回调函数
  cout << "timer_id=" << timer_id << endl;
  WaitForSingleObject(hEvent, 5000);
  cout << "WaitForSingleObject end" << endl;
  CloseHandle(hEvent);
  return 0;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam) {
  switch (uMessage) {
  case WM_CREATE:
    break;

  case WM_CLOSE:
    DestroyWindow(hWnd);
    break;

  case WM_DESTROY:
    PostQuitMessage(EXIT_SUCCESS);
    break;
  default:;
  }

  return DefWindowProc(hWnd, uMessage, wParam, lParam);
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCommandLine, int nShowCommand) {
  // define variables
  HWND hWnd;
  WNDCLASS wc;
  MSG msg;

  // unused parameters
  UNREFERENCED_PARAMETER(hPrevInstance);
  UNREFERENCED_PARAMETER(lpszCommandLine);
  UNREFERENCED_PARAMETER(nShowCommand);

  // initialize WNDCLASS structure
  ZeroMemory(&wc, sizeof(wc));
  wc.lpfnWndProc = WndProc;
  wc.hInstance = hInstance;
  wc.lpszClassName = gc_szClassName;

  // attempt to register the class
  if (RegisterClass(&wc) != 0) {
    // show console
    AllocConsole();
    std::ignore = freopen_s((FILE**)stdout, "CONOUT$", "w", stdout);
    std::ignore = freopen_s((FILE**)stdout, "CONOUT$", "w", stderr);
    std::ignore = freopen_s((FILE**)stdout, "CONIN$", "r", stdin);
    std::cout.clear();
    std::clog.clear();
    std::cerr.clear();
    std::cin.clear();

    // attempt to create the window
    hWnd = CreateWindow(gc_szClassName, gc_szWindowTitle, WS_CAPTION | WS_SYSMENU | WS_VISIBLE, 100, 100, 100, 100, NULL, NULL, hInstance, NULL);
    cout << "window hwnd=" << hWnd << endl;

    const HANDLE thread_handle = CreateThread(nullptr, 0, thread, &hWnd, 0, nullptr);

    int Counter = 0;
    // retrieve messages
    while (GetMessage(&msg, NULL, 0, 0) > 0) {
      ++Counter;
      std::cout << "Counter: " << Counter << "; message: " << msg.message << '\n';
      TranslateMessage(&msg);
      DispatchMessage(&msg);
    }
    // use the return-code from the window
    return (int)msg.wParam;
  }
  return EXIT_FAILURE;
}

2.png

将注入函数转为汇编语言

转为汇编语言这一步骤我卡住好几天。转为汇编语言本进程执行很简单,但如果要把thread()、timerproc()、call()三个函数在远程进程运行则有难度。主要难度为注入到远程进程后,由于没有基址重定位,无法执行call系统函数语句CALL KillTimer,也无法执行call自有函数语句CALL call。

研究了几天之后发现受限于内联汇编的功能局限性,不能用内联汇编完成目的。所以简单学习了一下asmjit,改用asmjit汇编引擎实现功能。

本进程执行代码

接下来需要将thread()、Timerproc()、call()函数转换为汇编语言。转换后的完整代码如下:

#include <iostream>
#include <windows.h>

using namespace std;

HANDLE hEvent;

void call() {
  //cout << "func call start" << endl;
  //int a = 1, b = 0, c = 0;
  //c = a / b;  // 这句代码会引发异常,除数为零
  //cout << "func call end" << endl;

  char start[] = "func call start\n";
  char end[] = "func call end\n";
  __asm {
    lea eax, start
    push eax
    call printf
    xor eax, eax
    div eax // 0除以0 异常语句
    lea eax, end
    push eax
    call printf
  }
}

// 计时器回调函数
VOID CALLBACK Timerproc(
  HWND hwnd,        // handle to window for timer messages 
  UINT message,     // WM_TIMER message 
  UINT idTimer,     // timer identifier 
  DWORD dwTime)     // current system time
{
  //cout << "Timerproc" << endl;
  //if (KillTimer(hwnd, idTimer))
  //  cout << "KillTimer done" << endl;
  //else
  //  cout << "KillTimer error" << endl;
  //call(); // 如果函数内异常导致退出,则不会执行下面的代码
  //SetEvent(hEvent);

  __asm {
    push idTimer
    push hwnd
    call KillTimer
    call call
    //mov dword ptr ds : [0x12345678] , eax;  // 把call函数的返回值结果存放到指定的内存地址
    push hEvent
    call SetEvent
  }
}

DWORD WINAPI thread(_In_ LPVOID lpParameter) {
  HWND process_hwnd = *(HWND*)lpParameter;
  UINT_PTR timer_id;
  //cout << "process_hwnd=" << process_hwnd << endl;
  //cout << "thread start PID=" << GetCurrentThreadId() << endl;
  //const HANDLE thread_hwnd = GetCurrentThread();
  ////hEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);
  //timer_id = SetTimer(nullptr, 0, 0, nullptr);
  //timer_id = SetTimer(process_hwnd,      // 绑定的窗口句柄
  //                    timer_id,     // timer ID
  //                    0x0,          // 倒计时数,毫秒
  //                    Timerproc);   // 回调函数
  //cout << "timer_id=" << timer_id << endl;
  //WaitForSingleObject(hEvent, 5000);
  //cout << "WaitForSingleObject end" << endl;
  //CloseHandle(hEvent);

  char start[] = "func thread start\n";
  char end[] = "func thread end\n";
  __asm {
    lea eax, start
    push eax
    call printf
    push 0
    push 0
    push 0
    push 0
    call CreateEvent
    mov hEvent, eax
    push 0
    push 0
    push 0
    push 0
    call SetTimer
    push Timerproc
    push 0
    push eax
    push process_hwnd
    call SetTimer
    mov timer_id, eax
    push 0x1388; 5000毫秒
    push hEvent
    call WaitForSingleObject
    push hEvent
    call CloseHandle
    lea eax, end
    push eax
    call printf
  }
  return 0;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam) {
  switch (uMessage) {
  case WM_CREATE:
    break;

  case WM_CLOSE:
    DestroyWindow(hWnd);
    break;

  case WM_DESTROY:
    PostQuitMessage(EXIT_SUCCESS);
    break;
  default:;
  }

  return DefWindowProc(hWnd, uMessage, wParam, lParam);
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCommandLine, int nShowCommand) {
  // define variables
  HWND hWnd;
  WNDCLASS wc;
  MSG msg;

  // unused parameters
  UNREFERENCED_PARAMETER(hPrevInstance);
  UNREFERENCED_PARAMETER(lpszCommandLine);
  UNREFERENCED_PARAMETER(nShowCommand);

  // initialize WNDCLASS structure
  ZeroMemory(&wc, sizeof(wc));
  wc.lpfnWndProc = WndProc;
  wc.hInstance = hInstance;
  wc.lpszClassName = TEXT("class name");

  // attempt to register the class
  if (RegisterClass(&wc) != 0) {
    AllocConsole();
    std::ignore = freopen_s((FILE**)stdout, "CONOUT$", "w", stdout);
    std::ignore = freopen_s((FILE**)stdout, "CONOUT$", "w", stderr);
    std::ignore = freopen_s((FILE**)stdout, "CONIN$", "r", stdin);
    std::cout.clear();
    std::clog.clear();
    std::cerr.clear();
    std::cin.clear();

    // attempt to create the window
    hWnd = CreateWindow(TEXT("class name"), TEXT("window title"), WS_CAPTION | WS_SYSMENU | WS_VISIBLE, 1100, 600, 100, 100, NULL, NULL, hInstance, NULL);
    cout << "window hwnd=" << hWnd << endl;

    const HANDLE thread_handle = CreateThread(nullptr, 0, thread, &hWnd, 0, nullptr);

    int Counter = 0;
    // retrieve messages
    while (GetMessage(&msg, NULL, 0, 0) > 0) {
      ++Counter;
      std::cout << "Counter: " << Counter << "; message: " << msg.message << '\n';
      TranslateMessage(&msg);
      DispatchMessage(&msg);
    }
    // use the return-code from the window
    return (int)msg.wParam;
  }
  return EXIT_FAILURE;
}

3.png

运行成功。实际应用时可以把call函数里的两个调试printf语句删了。

远程进程执行代码

代码只适用于x86程序,如果你系统是64位系统,测试用的笔记本程序需要使用c:\windows\SysWOW64\notepad.exe

#include <algorithm>
#include <format>
#include <iomanip>
#include <windows.h>
#include <iostream>
#include <psapi.h>
#include <string>
#include <asmjit/asmjit.h>

using namespace std;
using namespace asmjit;
using namespace x86;

struct THREAD_PARAM {
  DWORD ret_value;    // alloc_addr + 0x0
  FARPROC settimer;   // alloc_addr + 0x4
  FARPROC killtimer;  // alloc_addr + 0x8
  HWND remote_hwnd;   // alloc_addr + 0xC
  DWORD timerproc;    // alloc_addr + 0x10
  DWORD timer_id;     // alloc_addr + 0x14
  DWORD custom_call;  // alloc_addr + 0x18
};

/**
 * \brief 获取指定进程中的模块函数句柄
 * \param hRemoteProcess 指定进程句柄
 * \param lpModuleName 指定函数名所在的模块名,大小写任意
 * \param lpProcName 指定要获取的函数名,大小写必须匹配
 * \return 成功则返回指定的函数地址,未找到返回空指针
 * \note 可至微软learn网站查询函数所在的模块
 */
FARPROC GetRemoteModule(_In_ const HANDLE hRemoteProcess, _In_ const LPCWSTR lpModuleName, _In_ const LPCSTR lpProcName) {
  // https://learn.microsoft.com/zh-cn/windows/win32/psapi/enumerating-all-modules-for-a-process

  // 获取远程模块信息
  HMODULE hModule[MAX_PATH];
  DWORD cbNeeded;
  if (!EnumProcessModules(hRemoteProcess, hModule, MAX_PATH, &cbNeeded))
    return nullptr;

  // 遍历枚举到的模块
  for (size_t i = 0; i < cbNeeded / sizeof(HMODULE); i++) {
    TCHAR szModName[MAX_PATH];

    // Get the full path to the module's file.
    if (GetModuleFileNameEx(hRemoteProcess, hModule[i], szModName,
                            sizeof(szModName) / sizeof(TCHAR))) {
      // 转为wstring字符串,并全部转换为小写以便比较
      wstring ModName(szModName);
      wstring ModuleName(lpModuleName);
      ranges::transform(ModName, ModName.begin(), ::tolower);
      ranges::transform(ModuleName, ModuleName.begin(), ::tolower);

      //wcout << format(L"\t0x{:08X} {}\n", (DWORD)hModule[i], ModName);

      // 如果是要找的模块
      if (ModName.find(ModuleName) != wstring::npos)
        // 如果GetProcAddress函数成功,则返回值是导出的函数或变量的地址。如果GetProcAddress函数失败,则返回值为 NULL。 要获得更多的错误信息,请调用 GetLastError。
        return GetProcAddress(hModule[i], lpProcName);
    }
  }
  return nullptr;
}

int main() {
  const HWND remote_hwnd =
    FindWindow(L"Notepad", nullptr);
  cout << "remote_hwnd=" << remote_hwnd << endl;

  DWORD remote_pid = 0;
  GetWindowThreadProcessId(remote_hwnd, &remote_pid);
  cout << "remote_pid=" << remote_pid << endl;

  const HANDLE remote_handle = OpenProcess(PROCESS_ALL_ACCESS, false, remote_pid);
  if (!remote_handle)
    return 0;

  // 获取远程进程模块函数信息
  auto settimer = GetRemoteModule(remote_handle, TEXT("User32.dll"), "SetTimer");
  auto killtimer = GetRemoteModule(remote_handle, TEXT("User32.dll"), "KillTimer");
  //cout << format("SetTimer addr=0x{:08X}\n", (DWORD)settimer);
  //cout << format("KillTimer addr=0x{:08X}\n", (DWORD)killtimer);

  // 申请远程空间,写入和执行权限
  DWORD alloc_addr = (DWORD)VirtualAllocEx(remote_handle, nullptr, MAX_PATH, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
  if (!alloc_addr) {
    cout << "GetLastError()=" << GetLastError() << endl;
    return 0;
  }
  cout << setw(8) << setfill('0') << hex << "VirtualAlloc addr=0x" << alloc_addr << endl;
  DWORD addr_param = alloc_addr;  // 参数内存地址
  DWORD addr_call = alloc_addr + 0x21;  // 函数地址

  // 构造和写入函数
  THREAD_PARAM thread_param{};
  thread_param.remote_hwnd = remote_hwnd;
  thread_param.settimer = settimer;
  thread_param.killtimer = killtimer;

  // 生成代码
  JitRuntime rt;
  auto a = x86::Assembler();
  CodeHolder code;
  code.init(rt.environment(), rt.cpuFeatures());
  code.attach(&a);

  // 构造thread函数
  a.push(0);
  a.push(0);
  a.push(0);
  a.push(0);
  a.call(dword_ptr(alloc_addr + 0x4));  // settimer
  a.mov(dword_ptr(alloc_addr + 0x14), eax); //timer_id
  a.push(dword_ptr(alloc_addr + 0x10));  // timerproc
  a.push(0);
  a.push(eax);
  a.push(dword_ptr(alloc_addr + 0xC));  // remote_hwnd
  a.call(dword_ptr(alloc_addr + 0x4));  // settimer
  a.ret();
  CodeBuffer& thread = code.textSection()->buffer();  // 获取对应的机器码
  // 打印生成的机器码
  //cout << "assembly=";
  //for (auto& i : thread)
  //  cout << format("{:02X} ", i);
  //cout << endl;

  size_t nSize = thread.size();
  cout << format("线程函数写入地址=0x{:08X} 大小=0x{:08X}\n", addr_call, nSize);
  WriteProcessMemory(remote_handle, (LPVOID)addr_call, thread.data(), nSize, nullptr);
  DWORD thread_addr = addr_call; // 记录线程函数地址
  addr_call = addr_call + nSize + 0x8;

  // 重置并复用CodeHolder变量code
  code.reset();
  code.init(rt.environment(), rt.cpuFeatures());
  code.attach(&a);

  // 构造timerproc
  a.push(dword_ptr(alloc_addr + 0x14)); // idTimer
  a.push(dword_ptr(alloc_addr + 0xC));  // hwnd
  a.call(dword_ptr(alloc_addr + 0x8)); // call KillTimer
  a.call(dword_ptr(alloc_addr + 0x18)); // custom_call
  a.ret();
  CodeBuffer& timerproc = code.textSection()->buffer();

  thread_param.timerproc = addr_call; // 记录therad地址
  nSize = timerproc.size();
  cout << format("回调函数写入地址=0x{:08X} 大小=0x{:08X}\n", addr_call, nSize);
  WriteProcessMemory(remote_handle, (LPVOID)addr_call, timerproc.data(), nSize, nullptr);
  addr_call = addr_call + nSize + 0x8;

  // 重置并复用CodeHolder变量code
  code.reset();
  code.init(rt.environment(), rt.cpuFeatures());
  code.attach(&a);

  // 构造自定函数
  a.xor_(eax, eax);
  a.div(eax); // 异常语句
  a.mov(dword_ptr(alloc_addr), eax);  // 写入返回值到alloc_addr,程序读取alloc_addr地址的数值即可知道返回值
  a.ret();
  CodeBuffer& custom_call = code.textSection()->buffer();

  thread_param.custom_call = addr_call; // 记录custom_call地址
  nSize = custom_call.size();
  cout << format("自定函数写入地址=0x{:08X} 大小=0x{:08X}\n", addr_call, nSize);
  WriteProcessMemory(remote_handle, (LPVOID)addr_call, custom_call.data(), nSize, nullptr);
  addr_call = addr_call + nSize + 0x8;

  // 写入参数
  cout << format("线程参数写入地址=0x{:08X} 大小=0x{:08X}\n", addr_param, sizeof(THREAD_PARAM));
  WriteProcessMemory(remote_handle, (LPVOID)addr_param, &thread_param, sizeof(THREAD_PARAM), nullptr);

  const HANDLE hRemoteThread = CreateRemoteThread(remote_handle, nullptr, 0, (LPTHREAD_START_ROUTINE)thread_addr, (LPVOID)addr_param, 0, nullptr);

  //system("pause");
  return 0;
}

5.png

免费评分

参与人数 3威望 +1 吾爱币 +22 热心值 +3 收起 理由
苏紫方璇 + 1 + 20 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
JUNWO999 + 1 + 1 我很赞同!
夫子点灯 + 1 + 1 我很赞同!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

lllwhh 发表于 2024-6-16 12:56
感谢分享!
xlhwxyh 发表于 2024-6-16 13:16
不懂,也不知道这么弄又啥用处! 用来干啥的?
hanyugeng0125 发表于 2024-6-16 14:26
苏紫方璇 发表于 2024-6-16 14:51
测试控制台是可以的
[C++] 纯文本查看 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <conio.h>

void WINAPI tfun(HWND, UINT, UINT_PTR, DWORD)
{
	int a;
	a = 1;
	a = 1 / (a - a);
	memcpy(0, 0, 1);
	return;
}

int main() {
	
	int timerId =SetTimer(0, 1, 1000, tfun);
	// 模拟消息循环
	MSG msg;
	while (true) {
		// 等待并处理消息
		while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
			if (msg.message == WM_QUIT) {
				break;
			}
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}

		// 如果用户按下回车键,则退出循环
		if (_kbhit() && _getch() == '\r') {
			break;
		}

		Sleep(100); // 睡眠一段时间以避免CPU占用过高
	}

	// 销毁定时器
	KillTimer(NULL, timerId);

	
	return 0;
}
你是猪饿 发表于 2024-6-16 16:59
感谢大佬的东西,为什么你这么优秀
 楼主| king1027 发表于 2024-6-16 21:23
本帖最后由 king1027 于 2024-6-16 21:44 编辑
苏紫方璇 发表于 2024-6-16 14:51
测试控制台是可以的
[mw_shl_code=cpp,true]#include
#include

这是本进程循环,肯定没问题。

问题是把tfun注入远程进程以后,tfun里调用settimer、killtimer函数,基址没有重定位,无法直接CALL函数,还有再调用自定函数也不行,还有函数的参数也不好搞
lduml 发表于 2024-6-16 21:59
太优秀了,mark
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-24 19:07

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表