I'm trying make a hook in MessageBoxA api in a remote process made by me using IAT hook tecnique. I'm using Process Hacker software for inject my dll file into my process and until here works fine.
My unique trouble is that MessageBoxA never is intercepted when i will call this api from my application.
I have discovered that this api don't can be found in table of import of my process.
So, i want know any suggestion about how i can find this api on table.
Here is code that i use:
#include <windows.h>
#include <string.h>
#include <stdio.h>
void HookFunction(char* funcName, LPDWORD function);
LPDWORD FoundIAT(char* funcName);
int WINAPI HookMessageBoxA(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType);
BOOL APIENTRY DllMain (HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
if(dwReason == DLL_PROCESS_ATTACH)
{
MessageBox(NULL, "Injeted with success!", "Hello", NULL);
HookFunction("MessageBoxA", (LPDWORD)&HookMessageBoxA);
}
return TRUE;
}
void HookFunction(char* funcName, LPDWORD function)
{
LPDWORD pOldFunction = FoundIAT(funcName);
DWORD accessProtectionValue , accessProtec;
int vProtect = VirtualProtect(pOldFunction, sizeof(LPDWORD), PAGE_EXECUTE_READWRITE, &accessProtectionValue);
*pOldFunction = (DWORD)function;
vProtect = VirtualProtect(pOldFunction, sizeof(LPDWORD), accessProtectionValue, &accessProtec);
}
int WINAPI HookMessageBoxA(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType)
{
return MessageBoxA(hWnd, "Hello", "DLL answering here!", uType);
}
LPDWORD FoundIAT(char* funcName)
{
DWORD test = 0;
LPVOID pMapping = GetModuleHandle(NULL);
if (pMapping == NULL)
exit(-1);
PIMAGE_DOS_HEADER DosHeader = (PIMAGE_DOS_HEADER) pMapping;
if (DosHeader->e_magic != IMAGE_DOS_SIGNATURE)
exit(-1);
PIMAGE_NT_HEADERS NtHeaders = (PIMAGE_NT_HEADERS) ((char*) DosHeader + DosHeader->e_lfanew);
if (NtHeaders->Signature != IMAGE_NT_SIGNATURE)
exit(-1);
PIMAGE_DATA_DIRECTORY DataDirectory = &NtHeaders->OptionalHeader.DataDirectory[1];
PIMAGE_IMPORT_DESCRIPTOR ImportDescriptor = (PIMAGE_IMPORT_DESCRIPTOR) ((char*) DosHeader + DataDirectory->VirtualAddress);
PIMAGE_THUNK_DATA32 OriginalFirstThunk = (PIMAGE_THUNK_DATA32)((char*) DosHeader + ImportDescriptor->OriginalFirstThunk);
while(OriginalFirstThunk != 0)
{
DWORD name = (DWORD)((char*) pMapping + ImportDescriptor->Name);
OriginalFirstThunk = (PIMAGE_THUNK_DATA32)((char*) DosHeader + ImportDescriptor->OriginalFirstThunk);
PIMAGE_THUNK_DATA32 FirstThunk = (PIMAGE_THUNK_DATA32)((char*) DosHeader + ImportDescriptor->FirstThunk);
while(OriginalFirstThunk->u1.AddressOfData != 0)
{
PIMAGE_IMPORT_BY_NAME NameImg = (PIMAGE_IMPORT_BY_NAME)((char*) DosHeader + (DWORD)OriginalFirstThunk->u1.AddressOfData);
test = (DWORD)OriginalFirstThunk->u1.Function & (DWORD)IMAGE_ORDINAL_FLAG32;
if (test == 0)
{
if(strcmp(funcName, (const char*)NameImg->Name) == 0)
{
MessageBox(NULL, NameImg->Name, "", NULL);
return (LPDWORD)&(FirstThunk->u1.Function);
}
}
OriginalFirstThunk++;
FirstThunk++;
}
ImportDescriptor++;
}
return 0;
}
Source
EDIT 1:
I have seen with more datails, that now this code is able to find MessageBoxA api :D, but still when i'll call this api from my application (made in Delphi), the hook don't work.
:-(
My Delphi code here:
procedure TForm1.btn1Click(Sender: TObject);
begin
MessageBoxA(Application.Handle, 'Delphi application here!', 'Hello',0);
end;
EDIT 2:
This can be a definitive solution, but link is offline. Someone can help me about how it can be adapted to my code above please?
Related
My project contains managed part(dotnet) and native(C++) part. I want to hook Winapi CreateFiles in my project by detours and log callstack. Now I have obtained a native callstack by invoking CaptureStackBackTrace and SymFromAddr api in dbghelp. But I meet some troubles when those functions are used in dotnet. as shown in the following picture, it can obtain correct callstack of native code(22, 21, 1, 0) but not work for managed code(20-2). may I have some methods to obtain both managed(dotnet) and un-managed(C++) callstack correctly? or maybe you have the best method to get callstack, could you help me?
dotnet produce:
public class CreateFileOrFolder
{
public void writeToFile(string pathString) {
System.IO.File.Create(pathString);
}
static void Main()
{
System.Console.WriteLine("Press any key to start.\n");
System.Console.ReadKey();
string fileName = "c.txt";
string pathString = System.IO.Path.Combine(#"D:\JunFiles\testDotNetProceduce", fileName);
// Verify the path that you have constructed.
Console.WriteLine("Path to my file: {0}\n", pathString);
CreateFileOrFolder creater = new CreateFileOrFolder();
if (!System.IO.File.Exists(pathString)) {
creater.writeToFile(pathString);
}
else
{
System.IO.File.Delete(pathString);
Console.WriteLine("File \"{0}\" already exists. but now it is deleted\n", fileName);
creater.writeToFile(pathString);
}
}
}
detours hook function:
HANDLE(*__stdcall oldCreateFile)(LPCWSTR,
DWORD,
DWORD,
LPSECURITY_ATTRIBUTES,
DWORD,
DWORD,
HANDLE) = CreateFileW;
HANDLE WINAPI newCreateFile(
_In_ LPCWSTR lpFileName,
_In_ DWORD dwDesiredAccess,
_In_ DWORD dwShareMode,
_In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes,
_In_ DWORD dwCreationDisposition,
_In_ DWORD dwFlagsAndAttributes,
_In_opt_ HANDLE hTemplateFile
) {
static BOOL state = FALSE;
printStack();
symbolSolve(process);
printf("HOOK sucess!\n");
std::cout << current_working_directory() << endl;
wchar_t newFileName[] = L".\\newFile.txt";
return oldCreateFile(
newFileName, // L".\\NewFile.txt", // Filename
//lpFileName,
dwDesiredAccess, // Desired access
dwShareMode, // Share mode
lpSecurityAttributes, // Security attributes
dwCreationDisposition, // Creates a new file, only if it doesn't already exist
dwFlagsAndAttributes, // Flags and attributes
NULL);
}
get callstack:
#define STACK_INFO_LEN 200
static HANDLE process;
unsigned int i;
void* stack[100];
unsigned short frames;
SYMBOL_INFO* symbol;
std::queue<std::pair<void*, unsigned short>> myQueue;
PDWORD hashValue = (PDWORD)malloc(sizeof(DWORD));
void printStack(void)
{
frames = CaptureStackBackTrace(0, 100, stack, hashValue);
void* stackTmp = stack;
}
DWORD WINAPI symbolSolve(LPVOID p) {
int myqueue_size = myQueue.size();
char* szBriefInfo = NULL;
static const int MAX_STACK_FRAMES = 12;
void* pStack[MAX_STACK_FRAMES];
static char szStackInfo[STACK_INFO_LEN * MAX_STACK_FRAMES];
static char szFrameInfo[STACK_INFO_LEN];
if (szBriefInfo == NULL) {
strcpy_s(szStackInfo, "stack traceback:\n");
}
else {
strcpy_s(szStackInfo, szBriefInfo);
}
symbol = (SYMBOL_INFO*)calloc(sizeof(SYMBOL_INFO) + 256 * sizeof(char), 1);
symbol->MaxNameLen = 255;
symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
IMAGEHLP_LINE line;
line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
DWORD displacementLine = 0;
std::string strs = "";
strs += std::to_string(*hashValue);
for (i = 0; i < frames; i++) {
SymFromAddr(process, (DWORD64)(stack[i]), 0, symbol);
BOOL ret = SymGetLineFromAddr64(process, (DWORD64)(stack[i]), &displacementLine, &line);
_snprintf_s(szFrameInfo, sizeof(szFrameInfo), "%i: %s - 0x%0X ", frames - i - 1, symbol->Name, symbol->Address);
strcat_s(szStackInfo, szFrameInfo);
if (ret) {
_snprintf_s(szFrameInfo, sizeof(szFrameInfo), " | %s at %o \n", line.FileName, line.LineNumber);
strcat_s(szStackInfo, szFrameInfo);
}
else {
_snprintf_s(szFrameInfo, sizeof(szFrameInfo), "|error %d \n", GetLastError());
strcat_s(szStackInfo, szFrameInfo);
}
}
printf("%s \n", szStackInfo);
free(symbol);
return 0;
}
result:
The short answer is that dbhlp can't help with the managed parts of the stack walk.
It can be done, as windbg can do mixed mode stacks but it's specific to the version of .net and it also requires access to the full process memory to do it. I don't think the results from CaptureStackBackTrace will be enough, although since you are doing this in-process you may get away with it.
See the Mixed Mode Stackwalk article, which should give you pointers in the right direction.
I use detours to hook win32 api CreateFile and use CaptureStackBackTrace to get callstack information. and then resolve symbol by SymFromAddr api. but the result shown in terminal is only error 126 and error 184. And I only invoke ShowTraceStack function one time while trace information is more than one. I do not know what happened, can someone help me?
#include <windows.h>
#include <stdio.h>
#include "detours.h"
#include <fstream>
#include <Shlwapi.h>
#pragma comment(lib, "shlwapi.lib") //Windows API PathFileExists
#include <io.h>
#pragma comment(lib, "detours.lib")
#include <DbgHelp.h> //SymInitialize
#pragma comment(lib,"dbghelp.lib")
#define STACK_INFO_LEN 20000
struct stackInfo {
PDWORD hashValue; // hash value to identify same stack
char* szBriefInfo; // callstack info
};
stackInfo ShowTraceStack(char* szBriefInfo)
{
static const int MAX_STACK_FRAMES = 200;
void* pStack[MAX_STACK_FRAMES];
static char szStackInfo[STACK_INFO_LEN * MAX_STACK_FRAMES];
static char szFrameInfo[STACK_INFO_LEN];
HANDLE process = GetCurrentProcess(); // The handle used must be unique to avoid sharing a session with another component,
SymInitialize(process, NULL, TRUE);
PDWORD hashValue = (PDWORD)malloc(sizeof(DWORD)); // allow memory for hashVavlue, it will be rewrited in function CaptureStackBackTrace
WORD frames = CaptureStackBackTrace(0, MAX_STACK_FRAMES, pStack, hashValue);
//printf("hash value is: %ud \n", &hashValue);
if (szBriefInfo == NULL) {
strcpy_s(szStackInfo, "stack traceback:\n");
}
else {
strcpy_s(szStackInfo, szBriefInfo);
}
for (WORD i = 0; i < frames; ++i) {
DWORD64 address = (DWORD64)(pStack[i]);
DWORD64 displacementSym = 0;
char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)];
PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer;
pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
pSymbol->MaxNameLen = MAX_SYM_NAME;
DWORD displacementLine = 0;
IMAGEHLP_LINE64 line;
line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
if (SymFromAddr(process, address, &displacementSym, pSymbol) &&
SymGetLineFromAddr64(process, address, &displacementLine, &line))
{
_snprintf_s(szFrameInfo, sizeof(szFrameInfo), "\t%s() at %s:%d(0x%x)\n",
pSymbol->Name, line.FileName, line.LineNumber, pSymbol->Address);
}
else
{
_snprintf_s(szFrameInfo, sizeof(szFrameInfo), "\terror: %d\n", GetLastError());
}
strcat_s(szStackInfo, szFrameInfo);
}
stackInfo traceStackInfo;
traceStackInfo.hashValue = hashValue;
traceStackInfo.szBriefInfo = szStackInfo;
printf("%s", szStackInfo);
return traceStackInfo;
}
HANDLE(*oldCreateFile)(LPCWSTR,
DWORD,
DWORD,
LPSECURITY_ATTRIBUTES,
DWORD,
DWORD,
HANDLE) = CreateFileW;
HANDLE WINAPI newCreateFile(
_In_ LPCWSTR lpFileName,
_In_ DWORD dwDesiredAccess,
_In_ DWORD dwShareMode,
_In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes,
_In_ DWORD dwCreationDisposition,
_In_ DWORD dwFlagsAndAttributes,
_In_opt_ HANDLE hTemplateFile
) {
ShowTraceStack((char*)"trace information.");
return oldCreateFile(
L".\\newFiles.txt", // L".\\NewFile.txt", // Filename
//lpFileName,
dwDesiredAccess, // Desired access
dwShareMode, // Share mode
lpSecurityAttributes, // Security attributes
dwCreationDisposition, // Creates a new file, only if it doesn't already exist
dwFlagsAndAttributes, // Flags and attributes
NULL);
}
void hook() {
DetourRestoreAfterWith();
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach(&(PVOID&)oldCreateFile, newCreateFile);
DetourTransactionCommit();
}
void unhook()
{
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourDetach(&(PVOID&)oldCreateFile, newCreateFile);
DetourTransactionCommit();
}
void myProcess() {
HANDLE hFile = CreateFile(TEXT(".\\CreateFileDemo.txt"),
GENERIC_WRITE | GENERIC_READ,
0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
OutputDebugString(TEXT("CreateFile fail!\r\n"));
}
// write to file
const int BUFSIZE = 4096;
char chBuffer[BUFSIZE];
memcpy(chBuffer, "Test", 4);
DWORD dwWritenSize = 0;
BOOL bRet = WriteFile(hFile, chBuffer, 4, &dwWritenSize, NULL);
ShowTraceStack((char*)"trace information.");
if (bRet)
{
OutputDebugString(TEXT("WriteFile success!\r\n"));
}
}
int main(){
hook();
myProcess();
unhook();
}
I am trying to use DLL to download an update for exe file.
#include "pch.h"
#include<tchar.h>
#include<urlmon.h>
#pragma comment (lib,"urlmon.lib")
int main()
{
TCHAR path[MAX_PATH];
GetCurrentDirectory(MAX_PATH, path);
wsprintf(path, TEXT("%s\\update.exe"), path);
//printf("Path: %S\n", path);
HRESULT res = URLDownloadToFile(NULL, _T("getupdate"), path, 0, NULL);
if (res == s_OK )
{
}
}
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD reason,
LPVOID lpReserved
)
{
if (reason == DLL_PROCESS_ATTACH)
{
// MessageBoxA(NULL, "hello world", "wlekfjkej", MB_OK);
main();
/* const auto thread = CreateThread(nullptr,
0, reinterpret_cast<LPTHREAD_START_ROUTINE>(main),
hModule,
0, nullptr);
*/
}
}
So the problem is - HRESULT returning s_OK response which stands for - everything is ok and file downloaded. But it doesnt...
How can i get this method to work ? maybe some alternatives to urldownload func to use here?
There is a launcher - a program in C++, which you need to run as administrator. The launcher launches another process as well on behalf of the administrator and because of this, third-party programs (AutoHotkey) running with the rights of a normal user can not access it. The second process does not require administrator rights, so I would like to implement the launch with the rights of a normal user. How to do it?
At the moment I'm running the process using boost::process::system.
Raymond Chen has a blog article on this very topic:
How can I launch an unelevated process from my elevated process and vice versa?
Going from an unelevated process to an elevated process is easy. You can run a process with elevation by passing the runas verb to ShellExecute or ShellExecuteEx.
Going the other way is trickier. For one thing, it's really hard to munge your token to remove the elevation nature properly. And for another thing, even if you could do it, it's not the right thing to do, because the unelevated user may be different from the elevated user.
...
The solution here is to go back to Explorer and ask Explorer to launch the program for you. Since Explorer is running as the original unelevated user, the program ... will run as [the user].
His article provides the following code to launch an unelevated process, and a detailed explanation of what the code is actually doing (the FindDesktopFolderView function mentioned below is defined in his Manipulating the positions of desktop icons blog article):
#define STRICT
#include <windows.h>
#include <shldisp.h>
#include <shlobj.h>
#include <exdisp.h>
#include <atlbase.h>
#include <stdlib.h>
// FindDesktopFolderView incorporated by reference
void GetDesktopAutomationObject(REFIID riid, void **ppv)
{
CComPtr<IShellView> spsv;
FindDesktopFolderView(IID_PPV_ARGS(&spsv));
CComPtr<IDispatch> spdispView;
spsv->GetItemObject(SVGIO_BACKGROUND, IID_PPV_ARGS(&spdispView));
spdispView->QueryInterface(riid, ppv);
}
void ShellExecuteFromExplorer(
PCWSTR pszFile,
PCWSTR pszParameters = nullptr,
PCWSTR pszDirectory = nullptr,
PCWSTR pszOperation = nullptr,
int nShowCmd = SW_SHOWNORMAL)
{
CComPtr<IShellFolderViewDual> spFolderView;
GetDesktopAutomationObject(IID_PPV_ARGS(&spFolderView));
CComPtr<IDispatch> spdispShell;
spFolderView->get_Application(&spdispShell);
CComQIPtr<IShellDispatch2>(spdispShell)
->ShellExecute(CComBSTR(pszFile),
CComVariant(pszParameters ? pszParameters : L""),
CComVariant(pszDirectory ? pszDirectory : L""),
CComVariant(pszOperation ? pszOperation : L""),
CComVariant(nShowCmd));
}
int __cdecl wmain(int argc, wchar_t **argv)
{
if (argc < 2) return 0;
CCoInitialize init;
ShellExecuteFromExplorer(
argv[1],
argc >= 3 ? argv[2] : L"",
argc >= 4 ? argv[3] : L"",
argc >= 5 ? argv[4] : L"",
argc >= 6 ? _wtoi(argv[5]) : SW_SHOWNORMAL);
return 0;
}
if we run as admin (more concrete have S-1-5-32-544 'Administrators' group enabled in token) we can open local system process token (it grant all needed to as access for 'Administrators').
so we can do next:
get self terminal session id
enable debug privileges in token, for be able open any process with
PROCESS_QUERY_LIMITED_INFORMATION
enumerate running processes in system
open process with PROCESS_QUERY_LIMITED_INFORMATION
open process token with TOKEN_QUERY|TOKEN_DUPLICATE
query token privileges - are it have
SE_ASSIGNPRIMARYTOKEN_PRIVILEGE and SE_INCREASE_QUOTA_PRIVILEGE -
it need for call CreateProcessAsUser and SE_TCB_PRIVILEGE it
require for WTSQueryUserToken
if token have all this privileges (LocalSystem token have) -
duplicate this token to TokenImpersonation type.
if need enable some of this 3 privileges in token
impersonate with this token
and now we can
call WTSQueryUserToken with self session id - for get not elevated
user token
and finally CreateProcessAsUser with this token
reset impersonation
code:
static volatile UCHAR guz;
ULONG RunNonElevated(_In_ ULONG SessionId,
_In_ HANDLE hToken,
_In_opt_ LPCWSTR lpApplicationName,
_Inout_opt_ LPWSTR lpCommandLine,
_In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes,
_In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes,
_In_ BOOL bInheritHandles,
_In_ DWORD dwCreationFlags,
_In_opt_ LPVOID lpEnvironment,
_In_opt_ LPCWSTR lpCurrentDirectory,
_In_ LPSTARTUPINFOW lpStartupInfo,
_Out_ LPPROCESS_INFORMATION lpProcessInformation)
{
ULONG err;
PVOID stack = alloca(guz);
ULONG cb = 0, rcb = FIELD_OFFSET(TOKEN_PRIVILEGES, Privileges[SE_MAX_WELL_KNOWN_PRIVILEGE]);
union {
PVOID buf;
::PTOKEN_PRIVILEGES ptp;
};
do
{
if (cb < rcb)
{
cb = RtlPointerToOffset(buf = alloca(rcb - cb), stack);
}
if (GetTokenInformation(hToken, ::TokenPrivileges, buf, cb, &rcb))
{
if (ULONG PrivilegeCount = ptp->PrivilegeCount)
{
int n = 3;
BOOL fAdjust = FALSE;
::PLUID_AND_ATTRIBUTES Privileges = ptp->Privileges;
do
{
switch (Privileges->Luid.LowPart)
{
case SE_ASSIGNPRIMARYTOKEN_PRIVILEGE:
case SE_INCREASE_QUOTA_PRIVILEGE:
case SE_TCB_PRIVILEGE:
if (!(Privileges->Attributes & SE_PRIVILEGE_ENABLED))
{
Privileges->Attributes |= SE_PRIVILEGE_ENABLED;
fAdjust = TRUE;
}
if (!--n)
{
err = NOERROR;
if (DuplicateTokenEx(hToken,
TOKEN_ADJUST_PRIVILEGES|TOKEN_IMPERSONATE,
0, ::SecurityImpersonation, ::TokenImpersonation,
&hToken))
{
if (fAdjust)
{
AdjustTokenPrivileges(hToken, FALSE, ptp, rcb, NULL, NULL);
err = GetLastError();
}
if (err == NOERROR)
{
if (SetThreadToken(0, hToken))
{
HANDLE hUserToken;
if (WTSQueryUserToken(SessionId, &hUserToken))
{
if (!CreateProcessAsUserW(hUserToken,
lpApplicationName,
lpCommandLine,
lpProcessAttributes,
lpThreadAttributes,
bInheritHandles,
dwCreationFlags,
lpEnvironment,
lpCurrentDirectory,
lpStartupInfo,
lpProcessInformation))
{
err = GetLastError();
}
CloseHandle(hUserToken);
}
else
{
err = GetLastError();
}
SetThreadToken(0, 0);
}
else
{
err = GetLastError();
}
}
CloseHandle(hToken);
}
else
{
err = GetLastError();
}
return err;
}
}
} while (Privileges++, --PrivilegeCount);
}
return ERROR_NOT_FOUND;
}
} while ((err = GetLastError()) == ERROR_INSUFFICIENT_BUFFER);
return err;
}
ULONG RunNonElevated(_In_opt_ LPCWSTR lpApplicationName,
_Inout_opt_ LPWSTR lpCommandLine,
_In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes,
_In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes,
_In_ BOOL bInheritHandles,
_In_ DWORD dwCreationFlags,
_In_opt_ LPVOID lpEnvironment,
_In_opt_ LPCWSTR lpCurrentDirectory,
_In_ LPSTARTUPINFOW lpStartupInfo,
_Out_ LPPROCESS_INFORMATION lpProcessInformation
)
{
ULONG SessionId;
if (!ProcessIdToSessionId(GetCurrentProcessId(), &SessionId))
{
return GetLastError();
}
BOOLEAN b;
RtlAdjustPrivilege(SE_DEBUG_PRIVILEGE, TRUE, FALSE, b);
ULONG err = NOERROR;
// much more effective of course use NtQuerySystemInformation(SystemProcessesAndThreadsInformation) here
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0), hToken;
if (hSnapshot != INVALID_HANDLE_VALUE)
{
PROCESSENTRY32W pe = { sizeof(pe) };
if (Process32FirstW(hSnapshot, &pe))
{
err = ERROR_NOT_FOUND;
do
{
if (pe.th32ProcessID && pe.th32ParentProcessID)
{
if (HANDLE hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pe.th32ProcessID))
{
if (OpenProcessToken(hProcess, TOKEN_QUERY|TOKEN_DUPLICATE, &hToken))
{
err = RunNonElevated(
SessionId,
hToken,
lpApplicationName,
lpCommandLine,
lpProcessAttributes,
lpThreadAttributes,
bInheritHandles,
dwCreationFlags,
lpEnvironment,
lpCurrentDirectory,
lpStartupInfo,
lpProcessInformation);
CloseHandle(hToken);
}
else
{
err = GetLastError();
}
CloseHandle(hProcess);
}
else
{
err = GetLastError();
}
}
} while (err && Process32NextW(hSnapshot, &pe));
}
else
{
err = GetLastError();
}
CloseHandle(hSnapshot);
}
return err;
}
and test:
void test()
{
STARTUPINFO si = { sizeof(si)};
PROCESS_INFORMATION pi;
WCHAR ApplicationName[MAX_PATH];
if (GetEnvironmentVariableW(L"ComSpec", ApplicationName, RTL_NUMBER_OF(ApplicationName)))
{
if (!RunNonElevated(ApplicationName, L"cmd /k whoami.exe /priv /groups",0,0,0,0,0,0,&si, &pi))
{
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
}
}
with this we can not only run not elevated process, but ,if need, start it with duplicated handles
I had written a file monitor using ms detours.i have to hook file related calls like creatfile,readfile in any targetexecutable and collect stats from those calls.
I have an injector
void CFileStat::MonitorProcess()
{
int npos=filename.ReverseFind('\\');
CString name=filename.Mid(npos+1);
WCHAR* DirPath = new WCHAR[MAX_PATH];
WCHAR* FullPath = new WCHAR[MAX_PATH];
GetCurrentDirectory(MAX_PATH, DirPath);
DWORD processID = FindProcessId(name);
if ( processID == 0 )
AfxMessageBox(L"Could not find ");
else
AfxMessageBox(L"Process ID is ");
swprintf_s(FullPath, MAX_PATH, L"%s\\%s", DirPath,strhookdll);
LPCTSTR lpszPrivilege = L"SeDebugPrivilege";
// Change this BOOL value to set/unset the SE_PRIVILEGE_ENABLED attribute
BOOL bEnablePrivilege = TRUE;
HANDLE hToken;
// Open a handle to the access token for the calling process. That is this running program
if(!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken))
{
printf("OpenProcessToken() error %u\n", GetLastError());
return ;
}
BOOL test = SetPrivilege(hToken, lpszPrivilege, bEnablePrivilege);
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processID);
if( ! hProcess )
{
return;
}
LPVOID LoadLibraryAddr = (LPVOID)GetProcAddress(GetModuleHandle(L"kernel32.dll"),
"LoadLibraryA");
LPVOID LLParam = (LPVOID)VirtualAllocEx(hProcess, NULL, lstrlen(FullPath),
MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
if( ! LLParam )
{
printf( "ERROR: Problems with VirtualAllocEx. Error code: %d\n", GetLastError() );
return;
}
int n=WriteProcessMemory(hProcess, LLParam, FullPath, lstrlen(FullPath), NULL);
if(n == 0) {
printf("Error: there was no bytes written to the process's address space.\n");
}
HANDLE threadID = CreateRemoteThread(hProcess, NULL, NULL, (LPTHREAD_START_ROUTINE) LoadLibraryAddr,
LLParam, NULL, NULL);
if(threadID == NULL) {
printf("Error: the remote thread could not be created.\n");
}
else
{
printf("Success: the remote thread was successfully created.\n");
}
WaitForSingleObject(threadID, INFINITE);
CloseHandle(hProcess);
delete [] DirPath;
delete [] FullPath;
I have the hook dll
#include <iostream>
#include <windows.h>
#include "detours.h"
#include"FileDetour.h"
#pragma comment(lib, "detours.lib")
void AddHook(PVOID* func,PVOID intercept);
void DeleteHook(PVOID* func,PVOID intercept);
static HANDLE (WINAPI * PCreateFile)(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD
dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD
dwFlagsAndAttributes, HANDLE hTemplateFile) = CreateFile;
HANDLE WINAPI InterceptCreateFile(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD
dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition,
DWORD dwFlagsAndAttributes, HANDLE hTemplateFile);
BOOL APIENTRY DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpReserved )
{
FILE *file;
fopen_s(&file, "D:\\temp.txt", "a+");
DWORD Error=0;
// Perform actions based on the reason for calling.
switch( fdwReason )
{
case DLL_PROCESS_ATTACH:
// Initialize once for each new process.
// Return FALSE to fail DLL load.
fprintf(file, "DLL attach function called.\n");
DisableThreadLibraryCalls(hinstDLL);
OutputDebugString(L"Attaching filedetour.dll");
// DetourRestoreAfterWith();
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach(&(PVOID&)PCreateFile, InterceptCreateFile);
Error=DetourTransactionCommit();
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
// Do thread-specific cleanup.
break;
case DLL_PROCESS_DETACH:
fprintf(file, "DLL dettach function called.\n");
OutputDebugString(L"De-Attaching MyDLL.dll");
DWORD Error=0;
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourDetach(&(PVOID&)PCreateFile,InterceptCreateFile);
Error=DetourTransactionCommit();
break;
}
fclose(file);
return TRUE; // Successful DLL_PROCESS_ATTACH.
}
HANDLE WINAPI InterceptCreateFile(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD
dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD
dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile)
{
OutputDebugString(lpFileName);
return PCreateFile(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes,
dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
}
CreateRemotethread returns successfully and I am going to waitforsingleobject in the injector function.
but I am getting no evidence of dll being injected into the target exe process space.i tried ollydbg.the debug is not hitting the hook dll project named "filedetour" when i debug the target exe as well the injector process .Neither the text file temp.txt is being created.when i debug the target exe for one or two lines , I get a debug window message the thread is exiting.The waitforsingleobejct in the injector process immediately signals.
in short there is no evidence a dll was injected sucessfuly and that dllmain was hit at all.
how to debug the entire process?iwant to debug the hook dll throroughly from the target exe as the hook dll collects stats from the file operations.
what are the files I have to copy from the hook dll project(dll,lib,.h) and any extra settings to be made to the injector project?
I am new to this topic.