detours hooked CreateFile 函数触发堆栈溢出
Posted
技术标签:
【中文标题】detours hooked CreateFile 函数触发堆栈溢出【英文标题】:detours hooked CreateFile function triggers stack overflow 【发布时间】:2014-03-03 05:47:06 【问题描述】:当我尝试使用 Detours 来挂钩 CreateFile 时,当我的挂钩函数被调用时,我得到一个堆栈溢出错误。我正在尝试将文件名写入文件,然后调用原始文件,但它在 fopen 调用中失败并出现堆栈溢出错误。我通过 CreateRemoteThread 调用注入 dll。在目标进程中我们必须做一些特殊的堆栈分配吗?我对 Windows 开发和弯路相当陌生,但我对 C/C++ 相当了解,但绝不是专家。
#include "stdafx.h"
#include "detours.h"
#include <cstdio>
#include <ws2tcpip.h>
#include <windows.h>
#include <stdio.h>
#pragma comment(lib, "detours.lib")
//#pragma comment(lib, "detoured.lib")
#pragma comment(lib, "ws2_32.lib")
HANDLE (WINAPI *oldCreate)(LPCTSTR, DWORD, DWORD, LPSECURITY_ATTRIBUTES, DWORD,DWORD, HANDLE ) = CreateFile;
HANDLE WINAPI myCreate(LPCTSTR, DWORD, DWORD, LPSECURITY_ATTRIBUTES, DWORD,DWORD,HANDLE);
INT APIENTRY DllMain(HMODULE hDLL, DWORD Reason, LPVOID Reserved)
switch(Reason)
case DLL_PROCESS_ATTACH:
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach(&(PVOID&)oldCreate, myCreate);
DetourTransactionCommit();
break;
case DLL_PROCESS_DETACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
break;
return TRUE;
HANDLE WINAPI myCreate(LPCTSTR lpFileName , DWORD dwDesiredAccess, DWORD dwShareMode , LPSECURITY_ATTRIBUTES lpSecurityAttributes , DWORD dwCreationDisposition ,DWORD dwFlagsAndAttributes, HANDLE hTemplateFile)
int x= 3;
FILE *file = fopen("C:\\test.txt", "a+");
fprintf(file, "%s \n", lpFileName);
fclose(file);
return oldCreate(lpFileName,dwDesiredAccess,dwShareMode,lpSecurityAttributes,dwCreationDisposition,dwFlagsAndAttributes,hTemplateFile);
extern "C" __declspec(dllexport) void dummy(void)`enter code here`
return;
这是我正在使用的注入器代码
另外,这是我正在使用的注入器代码
#include "stdafx.h"
#include <windows.h>
#include <stdio.h>
#include "detours.h"
#pragma comment (lib, "detours.lib")
#define MAX_COMBINED 8192
BOOL SetPrivilege(
HANDLE hToken, // token handle
LPCTSTR Privilege, // Privilege to enable/disable
BOOL bEnablePrivilege // TRUE to enable. FALSE to disable
);
LPTSTR GetArguments(void)
LPWSTR *szArglist = NULL;
int nArgs;
LPWSTR wbuf = NULL;
wbuf = new WCHAR[MAX_COMBINED];
if (wbuf == NULL)
return NULL;
memset(wbuf, 0, MAX_COMBINED*sizeof(WCHAR));
szArglist = CommandLineToArgvW(GetCommandLineW(), &nArgs);
if(NULL == szArglist)
return NULL;
else
for(int i=2; i<nArgs; i++)
wcscat_s(wbuf, MAX_COMBINED, szArglist[i]);
wcscat_s(wbuf, MAX_COMBINED, L" ");
LocalFree(szArglist);
#ifdef _UNICODE
return wbuf;
#else
LPSTR abuf = new CHAR[MAX_COMBINED];
if (abuf == NULL)
return NULL;
memset(abuf, 0, MAX_COMBINED);
WideCharToMultiByte(CP_ACP, 0, wbuf, -1, abuf, MAX_COMBINED, NULL, NULL);
delete[] wbuf;
return abuf;
#endif
int _tmain(int argc, _TCHAR* argv[])
HANDLE hToken;
if(argc < 2)
printf("pass just pid]\n");
return 0;
char* DirPath = new char[MAX_PATH];
char* FullPath = new char[MAX_PATH];
GetCurrentDirectoryA(MAX_PATH, (LPSTR)DirPath);
sprintf_s(FullPath, MAX_PATH, "%s\\injector3.dll", DirPath);
printf("FullPath %s \n",FullPath);
if(!OpenThreadToken(GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, FALSE, &hToken))
if (GetLastError() == ERROR_NO_TOKEN)
if (!ImpersonateSelf(SecurityImpersonation))
return 1;
if(!OpenThreadToken(GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, FALSE, &hToken))
printf("OpenThreadToken\n");
return 1;
else
return 1;
// enable SeDebugPrivilege
if(!SetPrivilege(hToken, SE_DEBUG_NAME, TRUE))
printf("SetPrivilege");
// close token handle
CloseHandle(hToken);
// indicate failure
return 2;
HANDLE hProcess = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION |
PROCESS_VM_WRITE, FALSE, _wtoi(argv[1]));
if(hProcess == NULL)
DWORD x = GetLastError();
printf("HANDLE TO PROCESS FAILED on PID %d with error %d\n",_wtoi(argv[1]),x);
return 1;
LPVOID LoadLibraryAddr = (LPVOID)GetProcAddress(GetModuleHandleA("kernel32.dll"),
"LoadLibraryA");
if(LoadLibraryAddr == NULL)
printf("GET PROC ADDRESS FAILED on PID %s\n",argv[1]);
return 1;
LPVOID LLParam = (LPVOID)VirtualAllocEx(hProcess, NULL, strlen(FullPath),
MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
if(LLParam == NULL)
printf("VirtualAllocEx on PID %s\n",argv[1]);
return 1;
WriteProcessMemory(hProcess, LLParam, FullPath, strlen(FullPath), NULL);
CreateRemoteThread(hProcess, NULL, NULL, (LPTHREAD_START_ROUTINE)LoadLibraryAddr,
LLParam, NULL, NULL);
CloseHandle(hProcess);
delete [] DirPath;
delete [] FullPath;
BOOL SetPrivilege(
HANDLE hToken, // token handle
LPCTSTR Privilege, // Privilege to enable/disable
BOOL bEnablePrivilege // TRUE to enable. FALSE to disable
)
TOKEN_PRIVILEGES tp;
LUID luid;
TOKEN_PRIVILEGES tpPrevious;
DWORD cbPrevious=sizeof(TOKEN_PRIVILEGES);
if(!LookupPrivilegeValue( NULL, Privilege, &luid )) return FALSE;
//
// first pass. get current privilege setting
//
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
tp.Privileges[0].Attributes = 0;
AdjustTokenPrivileges(
hToken,
FALSE,
&tp,
sizeof(TOKEN_PRIVILEGES),
&tpPrevious,
&cbPrevious
);
if (GetLastError() != ERROR_SUCCESS) return FALSE;
//
// second pass. set privilege based on previous setting
//
tpPrevious.PrivilegeCount = 1;
tpPrevious.Privileges[0].Luid = luid;
if(bEnablePrivilege)
tpPrevious.Privileges[0].Attributes |= (SE_PRIVILEGE_ENABLED);
else
tpPrevious.Privileges[0].Attributes ^= (SE_PRIVILEGE_ENABLED &
tpPrevious.Privileges[0].Attributes);
AdjustTokenPrivileges(
hToken,
FALSE,
&tpPrevious,
cbPrevious,
NULL,
NULL
);
if (GetLastError() != ERROR_SUCCESS) return FALSE;
return TRUE;
/*
BOOL SetPrivilege(
HANDLE hToken, // token handle
LPCTSTR Privilege, // Privilege to enable/disable
BOOL bEnablePrivilege // TRUE to enable. FALSE to disable
)
TOKEN_PRIVILEGES tp = 0 ;
// Initialize everything to zero
LUID luid;
DWORD cb=sizeof(TOKEN_PRIVILEGES);
if(!LookupPrivilegeValue( NULL, Privilege, &luid ))
return FALSE;
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
if(bEnablePrivilege)
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
else
tp.Privileges[0].Attributes = 0;
AdjustTokenPrivileges( hToken, FALSE, &tp, cb, NULL, NULL );
if (GetLastError() != ERROR_SUCCESS)
return FALSE;
return TRUE;
*/
【问题讨论】:
【参考方案1】:您正在用您的 myCreate 替换 CreateFile。 当 fopen 调用 CreateFile 打开文件时,它会再次调用你的 myCreate,这将调用 fopen,它将调用 CreateFile 等等,直到你用完堆栈。 您可以调用 oldCreateFile 来打开文件进行输出,但您将无法使用 fprintf 等。
【讨论】:
我完全没有想到这一点。感谢您的帮助 当我在 lpFileName 中看到测试文件时,我可以只返回 oldCreate 吗? 这行得通,你可能不想记录对该文件的访问。另一种选择是在您输入 myCreate 函数时设置一个布尔标志,并在您离开时清除它。然后,如果设置了标志,则不要进行日志记录。请注意,这不会处理多个线程,您必须使用线程本地存储。 你知道为什么我不能用 lpFileName 做一个简单的 lstrcmp 来检查它是否是文件。它总是返回 1 (false)。 我猜fopen可能会更改传入的文件名。也许它会更改驱动器号的大小写或将\更改为/。我想不出它为什么会那样做。你能发布你的新代码吗?以上是关于detours hooked CreateFile 函数触发堆栈溢出的主要内容,如果未能解决你的问题,请参考以下文章
Detours Hook:GetVolumeInformation 随机卷序列
Detours简介 (拦截x86机器上的任意的win32 API函数)