May 2, 2016 11:34 AM
(This post was last modified: May 4, 2016 02:27 PM by Goodies.)
Solution:
All I had to do was return TRUE from the DllMain function. Apparently, if you don't return true, it will unload the DLL immediately.
I wrote a couple quick classes. These are split into 3 monolithic applications.
HookDLL- This is a .dll library.
InjectDLL - This is an .exe used to inject DLLs.
TestMe - This is an .exe that just loops calling message box over and over to test when it has been hooked.
EasyHook.hpp
Source.cpp
The DLL injector EXE has 2 files:
InjectDLL.hpp
InjectDLL.cpp
Source.cpp
The PID I change to the PID of the target application. This is the target:
The trouble is that this works fine in my local application. If I were to only run the EasyHook.hpp function and hook the MessageBoxA function, it works just fine. However, the trouble is that it is not working when I inject it into the target application. I am sure it has something to do with the way I define the functions or something, but I just don't know. This is my first experience with windows API, so any help is appreciated.
Video of what happens when I inject: (Click to View)
Video of it working correctly in a local application without injection: (Click to View)
All I had to do was return TRUE from the DllMain function. Apparently, if you don't return true, it will unload the DLL immediately.
I wrote a couple quick classes. These are split into 3 monolithic applications.
HookDLL- This is a .dll library.
InjectDLL - This is an .exe used to inject DLLs.
TestMe - This is an .exe that just loops calling message box over and over to test when it has been hooked.
EasyHook.hpp
PHP Code
<?php
#ifndef EASYHOOK_HPP
#define EASYHOOK_HPP
#include <cstdio>
#include <iostream>
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#ifdef __cplusplus
#define EC_BEG extern "C" {
#define EC_END }
#else
#define EC_BEG
#define EC_END
#endif
namespace EasyHook {
enum opcode {
LONGJUMP_SIZE = 0x05,
RELJUMP = 0xe9,
NOP = 0x90,
};
template<typename T, typename... Args>
struct WrapperSTD {
typedef T(WINAPI *Functor)(Args...);
WrapperSTD() = default;
};
template <typename T, typename... Args>
struct WrapperC {
typedef T(*Functor)(Args...);
WrapperC() = default;
};
template<typename T, typename... Args>
WrapperC<T, Args...> wrap(T(*func)(Args...)) {
return WrapperC<T, Args...>{};
}
template<typename T, typename... Args>
WrapperSTD<T, Args...> wrap(T(WINAPI *func)(Args...)) {
return WrapperSTD<T, Args...>{};
}
class Hook {
ULONG oldProtection = NULL;
public:
Hook() = default;
LPVOID HookLong(LPVOID target, LPVOID Destination, ULONG jumpSize = 5) {
LPVOID trampoline = NULL;
ULONG OldProtection = 0;
if (jumpSize < 5)
return 0;
if (!VirtualProtect((LPVOID)target, 1, PAGE_EXECUTE_READWRITE, &OldProtection))
return 0;
if (!(trampoline = VirtualAlloc(NULL, 1, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE))) {
VirtualProtect((LPVOID)target, 1, OldProtection, &OldProtection);
return 0;
}
memset(trampoline, opcode::NOP, jumpSize);
*(BYTE*)trampoline = opcode::RELJUMP;
*(ULONG*)((ULONG)trampoline + 1) = jumpSize;
trampoline = (LPVOID)((ULONG)trampoline + opcode::LONGJUMP_SIZE);
memcpy(trampoline, (LPVOID)target, jumpSize);
*(BYTE*)((ULONG)trampoline + jumpSize) = opcode::RELJUMP;
*(ULONG*)((ULONG)trampoline + jumpSize + 1) = (ULONG)target - (ULONG)trampoline - opcode::LONGJUMP_SIZE;
*(ULONG*)((ULONG)trampoline + jumpSize + 1 + sizeof(ULONG)) = (ULONG)target;
memset((LPVOID)target, opcode::NOP, jumpSize);
*(BYTE*)target = opcode::RELJUMP;
*(ULONG*)((ULONG)target + 1) = (ULONG)Destination - (ULONG)target - opcode::LONGJUMP_SIZE;
VirtualProtect((LPVOID)target, 1, OldProtection, &OldProtection);
return trampoline;
}
LPVOID UnhookLong(LPVOID trampoline) {
LPVOID original = NULL;
ULONG jumpSize = 0;
trampoline = (LPVOID)((ULONG)trampoline - sizeof(ULONG));
jumpSize = *(PULONG)trampoline;
original = (LPVOID)((ULONG)trampoline + jumpSize + opcode::LONGJUMP_SIZE);
return original;
}
};
}
#endif
Source.cpp
PHP Code
<?php
#include "EasyHook.hpp"
#include <iostream>
#include <iomanip>
EC_BEG
using MessageBoxAF = decltype(EasyHook::wrap(MessageBoxA))::Functor;
static int WINAPI MessageBoxA_H(_In_opt_ HWND hWnd, _In_opt_ LPCSTR lpText, _In_opt_ LPCSTR lpCaption, _In_ UINT uType);
static MessageBoxAF trampoline;
EC_END
static int WINAPI MessageBoxA_H(_In_opt_ HWND hWnd, _In_opt_ LPCSTR lpText, _In_opt_ LPCSTR lpCaption, _In_ UINT uType) {
std::cout << "Testing!\n";
lpText = "Hook Successful";
std::cout << (ULONG)trampoline << std::endl;
if (trampoline)
return trampoline(hWnd, lpText, lpCaption, uType);
return 0;
}
BOOL WINAPI DllMain(_In_ HINSTANCE hinstDLL, _In_ DWORD fdwReason, _In_ LPVOID lpvReserved) {
switch (fdwReason) {
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
std::cout << "Working\n";
std::cout << std::hex << MessageBoxA_H << std::endl;
trampoline = (MessageBoxAF)EasyHook::Hook().HookLong(
GetProcAddress(GetModuleHandleA("user32.dll"), "MessageBoxA"), MessageBoxA_H
);
std::cout << std::hex << trampoline << std::endl;
break;
};
}
The DLL injector EXE has 2 files:
InjectDLL.hpp
PHP Code
<?php
#ifndef INJECTDLL_HPP
#define INJECTDLL_HPP
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <tlhelp32.h>
#include <iostream>
#include <sstream>
#include <cstdio>
#include <vector>
#include <string>
namespace injection {
# define ERROR(error) std::cerr << error
# define SUCCESS(message) std::cout << message
using std::vector;
using std::string;
using std::stringstream;
vector<string> &split(const string &s, char delim, vector<string> &elems);
vector<string> split(const string &s, char delim);
string filename(string sFilePath);
typedef HMODULE(WINAPI* LoadLibraryA_F)(LPCTSTR lpFileName);
class dllinjector {
public:
dllinjector() = default;
bool inject(LPCSTR szProcName, LPCSTR szDLLPath) const; // provide a process name and DLL path
bool inject(DWORD dwPID, LPCSTR szDLLPath) const; // provide a process ID and DLL path
bool inject(HANDLE hProc, LPCSTR szDLLPath) const; // provide a handle to a process and DLL path
};
}
#endif//INJECTDLL_HPP
InjectDLL.cpp
PHP Code
<?php
#include "InjectDLL.hpp"
namespace injection {
vector<string> &split(const std::string &s, char delim, std::vector<std::string> &elems) {
stringstream ss(s);
string item;
while (getline(ss, item, delim))
elems.push_back(item);
return elems;
}
vector<string> split(const string &s, char delim) {
vector<string> elems;
split(s, delim, elems);
return elems;
}
string filename(string sFullPath) {
return split(sFullPath, '\\').back();
}
bool dllinjector::inject(HANDLE hProc, LPCSTR szDLLPath) const {
bool success = FALSE;
LPVOID lpBase = NULL;
HANDLE hThread = NULL;
FARPROC LoadLibraryAF = NULL;
DWORD dwPathSize = strlen(szDLLPath) + 1;
lpBase = VirtualAllocEx(hProc, NULL, dwPathSize, MEM_COMMIT, PAGE_READWRITE);
if (lpBase) {
if (WriteProcessMemory(hProc, lpBase, szDLLPath, dwPathSize, NULL)) {
LoadLibraryAF = GetProcAddress(GetModuleHandleA("Kernel32"), "LoadLibraryA");
hThread = CreateRemoteThread(hProc, NULL, 0, (LPTHREAD_START_ROUTINE)LoadLibraryAF, lpBase, 0, NULL);
if (hThread) {
WaitForSingleObject(hThread, INFINITE);
success = TRUE;
} else return false;
}
VirtualFreeEx(hProc, lpBase, 0, MEM_RELEASE);
} else return false;
return success;
}
bool dllinjector::inject(DWORD dwPID, LPCSTR szDLLPath) const {
HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID);
if (!hProc)
return false;
return inject(hProc, szDLLPath);
}
bool dllinjector::inject(LPCSTR szProcName, LPCSTR szDLLPath) const {
PROCESSENTRY32 entry;
entry.dwSize = sizeof(entry);
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);
if (Process32First(snapshot, &entry) == TRUE) {
while (Process32Next(snapshot, &entry) == TRUE) {
if (!strcmp(entry.szExeFile, szProcName)) {
HANDLE hProc = OpenProcess(
PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE |
PROCESS_VM_READ | PROCESS_ALL_ACCESS, FALSE, entry.th32ProcessID
);
if (hProc)
return inject(hProc, szDLLPath);
}
}
}
CloseHandle(snapshot);
return false;
}
}
Source.cpp
PHP Code
<?php
#include "InjectDLL.hpp"
#include <string>
#include <fstream>
#define DLLPATH "c:/users/austin archer/documents/visual studio 2015/Projects/HookDLL/Release/HookDLL.dll"
#define PID 11852 //PID of target application
using std::string;
using std::ifstream;
bool exists(string name) {
ifstream f(name.c_str());
bool ret = f.good();
return f.close(), ret;
}
int main(int argc, char **argv) {
if (!exists(DLLPATH))
return 0;
injection::dllinjector injector;
injector.inject(PID, DLLPATH);
//std::cin.ignore();
return 0;
}
The PID I change to the PID of the target application. This is the target:
PHP Code
<?php
#include <iostream>
#include <sstream>
#include <string>
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
using std::string;
using std::stringstream;
int main() {
unsigned long i = 0;
stringstream ss;
stringstream message;
message << "Testing my message. PID = " << GetCurrentProcessId() << "\0";
bool cont = true;
while (cont) {
ss.swap(stringstream());
ss << "Test #" << i++ << "\0";
cont = !(MessageBoxA(NULL, message.str().c_str(), ss.str().c_str(), MB_OKCANCEL) == IDCANCEL);
}
}
The trouble is that this works fine in my local application. If I were to only run the EasyHook.hpp function and hook the MessageBoxA function, it works just fine. However, the trouble is that it is not working when I inject it into the target application. I am sure it has something to do with the way I define the functions or something, but I just don't know. This is my first experience with windows API, so any help is appreciated.
Video of what happens when I inject: (Click to View)
Video of it working correctly in a local application without injection: (Click to View)
SRPP Discord Server
I am a professional network/cloud security architect.
My Old Tutorials
I am a professional network/cloud security architect.
My Old Tutorials


![[Image: vONZN5S.gif]](https://i.imgur.com/vONZN5S.gif)
![[Image: vsAeZDY.gif]](https://i.imgur.com/vsAeZDY.gif)