一个API HOOK的例子

一个API HOOK的例子
2010年07月20日
  /* 编译环境 VC++6.0 WIN2K/WINXP,工程类型WIN32 APP,编译参数见最后的说明 */
  #include
  #include /*线程操作API*/
  HINSTANCE hInst;/* 任务实例ID */
  HWND MainFrmhWnd; /* 主窗口句柄 */
  HFONT GlobalFont; /* 字体 */
  typedef struct { /* 提供给注入代码的执行参数 */
  DWORD MyID;/* 本任务ID */
  void *FunPtr;/* 替换的API入口 */
  } RemoteParam;
  /* 窗口类名和标题的定义 */
  #define MAINFRM_CLASS "MyHookApi"
  #define MAINFRM_TITLE "Api Hook Demo"
  ATOM MyRegisterClass(HINSTANCE hInstance);
  LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
  int APIENTRY WinMain(HINSTANCE hInstance,
  HINSTANCE hPrevInstance,
  LPSTR lpCmdLine,
  int nCmdShow)
  {
  MSG msg;
  MyRegisterClass(hInstance);
  hInst = hInstance;
  /* 创建主窗口 */
  MainFrmhWnd = CreateWindow(MAINFRM_CLASS, MAINFRM_TITLE, WS_OVERLAPPEDWINDOW,
  CW_USEDEFAULT, CW_USEDEFAULT, 200, 150, NULL, NULL, hInstance, NULL);
  if (!MainFrmhWnd)
  {
  return FALSE;
  }
  /* 显示窗口 */
  ShowWindow(MainFrmhWnd, nCmdShow);
  UpdateWindow(MainFrmhWnd);
  while (GetMessage(&msg, NULL, 0, 0))
  {
  if (!TranslateAccelerator(msg.hwnd, NULL, &msg))
  {
  TranslateMessage(&msg);
  DispatchMessage(&msg);
  }
  }
  return msg.wParam;
  }
  /* 注册窗体类 */
  ATOM MyRegisterClass(HINSTANCE hInstance)
  {
  WNDCLASSEX wcex;
  wcex.cbSize = sizeof(WNDCLASSEX);
  wcex.style = CS_HREDRAW | CS_VREDRAW;
  wcex.lpfnWndProc = (WNDPROC)WndProc;
  wcex.cbClsExtra = 0;
  wcex.cbWndExtra = 0;
  wcex.hInstance = hInstance;
  wcex.hIcon = LoadIcon(hInstance, (LPCTSTR)NULL);
  wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
  wcex.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
  wcex.lpszMenuName = NULL;
  wcex.lpszClassName = MAINFRM_CLASS;
  wcex.hIconSm = LoadIcon(wcex.hInstance, (LPCTSTR)NULL);
  return RegisterClassEx(&wcex);
  }
  /* 通过任务名称获得任务ID */
  DWORD GetTaskIdByName(char *TargetTaskName)
  {
  HANDLE hSnape;
  PROCESSENTRY32 ProcInfo;
  strupr(TargetTaskName);
  hSnape = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  ProcInfo.dwSize = sizeof(PROCESSENTRY32);
  if (Process32First(hSnape, &ProcInfo) == TRUE)
  {
  do
  {
  strupr(ProcInfo.szExeFile);
  if (strcmp(ProcInfo.szExeFile, TargetTaskName) == 0)
  {
  CloseHandle(hSnape);
  return ProcInfo.th32ProcessID;
  }
  } while(Process32Next(hSnape, &ProcInfo) == TRUE);
  }
  CloseHandle(hSnape);
  return 0;
  }
  /* 创建传递给注入代码的参数 */
  void * CreateDataStruct(HANDLE hProc, void *OldFunPtr)
  {
  RemoteParam remoteData;
  RemoteParam* pRemoteParam;
  ZeroMemory(&remoteData, sizeof(RemoteParam));
  remoteData.MyID = GetCurrentProcessId();
  remoteData.FunPtr = OldFunPtr;
  /* 在目标任务里申请一块空间保存参数 */
  pRemoteParam = (RemoteParam *)VirtualAllocEx(hProc, NULL, sizeof(RemoteParam), MEM_COMMIT, PAGE_READWRITE);
  /* 写入参数 */
  if (!WriteProcessMemory(hProc, pRemoteParam, &remoteData, sizeof(remoteData), 0))
  {
  MessageBox(MainFrmhWnd, "Write data to target process failed!", "Fail", MB_OK | MB_ICONERROR);
  return 0;
  }
  return pRemoteParam;
  }
  /*提升进程访问权限*/
  BOOL enableDebugPriv()
  {
  HANDLE hToken;
  LUID sedebugnameValue;
  TOKEN_PRIVILEGES tkp;
  if (!OpenProcessToken(GetCurrentProcess(),
  TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {
  return FALSE;
  }
  if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &sedebugnameValue)) {
  CloseHandle(hToken);
  return FALSE;
  }
  tkp.PrivilegeCount = 1;
  tkp.Privileges[0].Luid = sedebugnameValue;
  tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
  if (!AdjustTokenPrivileges(hToken, FALSE, &tkp, sizeof(tkp), NULL, NULL)) {
  CloseHandle(hToken);
  return FALSE;
  }
  return TRUE;
  }
  /* 注入代码 */
  HANDLE WINAPI MyOpenProcess(DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwProcessId)
  {
  HANDLE (*OldFunPtr)(DWORD, BOOL, DWORD);
  RemoteParam * MyParam = (RemoteParam *)0xEFEFEFEF;/* 此处地址会被修改,设置成EFEFEFEF是为了便于查找*/
  OldFunPtr = (HANDLE (*)(DWORD, BOOL, DWORD))MyParam->FunPtr;
  /* 如果不等于当前任务ID,则允许打开(调用旧入口)*/
  if (dwProcessId != MyParam->MyID)
  {
  return OldFunPtr(dwDesiredAccess, bInheritHandle, dwProcessId);
  }
  return 0;
  }
  /* 主函数,生成注入信息 */
  void ProtectSelf(char *TargetTaskName)
  {
  DWORD TPid;
  HANDLE hProc;
  void * ParamPtr, * InjectPtr, * OldPtr, *ReplacePtr;
  int JmpAddr, i;
  unsigned char JmpCode[5] = {0};
  unsigned char FunCode[4096] = {0};
  /* 提升访问权限 */
  enableDebugPriv();
  /* 获得目标任务的PID */
  TPid = GetTaskIdByName(TargetTaskName);
  if (TPid == 0)
  {
  MessageBox(MainFrmhWnd, "Task not found", "Fail", MB_OK | MB_ICONERROR);
  return;
  }
  /* 打开目标任务 */
  hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, TPid);
  if (hProc == 0)
  {
  MessageBox(MainFrmhWnd, "Open task failed", "Fail", MB_OK | MB_ICONERROR);
  return;
  }
  /*
  * 获得当前任务的要注入的API的地址,此地址是固定的,静态映射的,所以当前任务的地址
  * 等于目标任务的地址。
  */
  OldPtr = GetProcAddress(LoadLibrary("Kernel32"), "OpenProcess");
  if (OldPtr == NULL)
  {
  MessageBox(MainFrmhWnd, "Get old function entry failed", "Fail", MB_OK | MB_ICONERROR);
  CloseHandle(hProc);
  return;
  }
  /*
  * 申请两块地址,一个是保存注入代码,也就是自己的MyOpenProcess,另一块用于保存被覆盖的
  * 系统的旧的OpenProcess的代码(实际只有5字节)
  */
  InjectPtr = VirtualAllocEx(hProc, NULL, 4096, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
  ReplacePtr = VirtualAllocEx(hProc, NULL, 4096, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
  if (InjectPtr == NULL || ReplacePtr == NULL)
  {
  MessageBox(MainFrmhWnd, "Memory alloc failed!", "Fail", MB_OK | MB_ICONERROR);
  CloseHandle(hProc);
  return;
  }
  /* 创建并保存参数信息 */
  ParamPtr = CreateDataStruct(hProc, ReplacePtr);
  if (ParamPtr == NULL)
  {
  CloseHandle(hProc);
  return;
  }
  memset(FunCode, 0, 4096);
  /* 读出自身的这个函数到内存中 */
  memcpy(FunCode, &MyOpenProcess, 4096);
  for (i = 0; i 内存空间并写入代码完成的,自己的
  替换函数如果判断此次调用的参数中,进程ID不是要屏蔽的进程号,则调用
  系统旧的API,因为旧的API的前5个字节被替换成了LONG JMP,于是要把被
  替换下来的内容保存于一个新的内存块里,并把这块内存的最后再加上一个
  LONG JMP,跳转到实际的API的第5字节偏移处。
  因为系统的调用都是采用stdcall方式,所以本程序需要编译成stdcall的
  方式,否则会导致调用栈混乱,同时因为注入代码无法保存任何本任务内的
  全局变量,所以需要专门开辟一段内存空间保存这些参数信息。注入代码内
  不可以包含任何库、API函数调用,不能使用任何全局变量。
  为了运行正常的需要,建议把编译参数里的/GZ去掉,否则此参数会产生
  栈检查,可能会导致一些错误的地址出现。
  */
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值