📄 inject.c
字号:
if (!(hNTDll = LoadLibrary("NTDLL.DLL")))
return -1;
// Load ZwQuerySystemInformation() dynamically
if (!(ZwQuerySystemInformation = (ZWQUERYSYSTEMINFORMATION)GetProcAddress(hNTDll, "ZwQuerySystemInformation")))
{
FreeLibrary(hNTDll);
SetLastError(ERROR_PROC_NOT_FOUND);
return -1;
}
// Find needed buffer length
do
{
if (!(pBuffer = malloc(BufferLen)))
{
FreeLibrary(hNTDll);
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return -1;
}
Status = ZwQuerySystemInformation(SystemProcessesAndThreadsInformation,
pBuffer, BufferLen, NULL);
if (Status == STATUS_INFO_LENGTH_MISMATCH)
{
free(pBuffer);
BufferLen *= 2;
}
else if (!NT_SUCCESS(Status))
{
free(pBuffer);
FreeLibrary(hNTDll);
return -1;
}
}
while (Status == STATUS_INFO_LENGTH_MISMATCH);
pInfo = (PSYSTEM_PROCESSES)pBuffer;
for (;;)
{
pszProcessName = pInfo->ProcessName.Buffer;
if (pszProcessName == NULL)
pszProcessName = L"Idle";
// Process found ?
if (wcsicmp(pszProcessName, wcProcessName) == 0)
{
dwPID = pInfo->ProcessId;
free(pBuffer);
FreeLibrary(hNTDll);
return dwPID;
}
if (pInfo->NextEntryDelta == 0)
break;
// Find the address of the next process structure
pInfo = (PSYSTEM_PROCESSES)(((PUCHAR)pInfo) + pInfo->NextEntryDelta);
}
free(pBuffer);
FreeLibrary(hNTDll);
return -1;
}
/********************************
* Return PID for Process Name. *
********************************/
DWORD GetPIDFromName(char *szProcessName)
{
DWORD dwPID;
OSVERSIONINFO info;
info.dwOSVersionInfoSize = sizeof(info);
GetVersionEx(&info);
// Get PID using Toolhelp or ZwQuerySystemInformation() depending on the OS version
if (info.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
dwPID = GetPIDFromNameToolhelp(szProcessName);
else if (info.dwPlatformId == VER_PLATFORM_WIN32_NT)
dwPID = GetPIDFromNameZwQuerySystemInformation(szProcessName);
else
dwPID = -1;
return dwPID;
}
/////////////////////////////////////////////// Inject DLL ////////////////////////////////////////////
extern HINSTANCE hInst; // Instance handle
DWORD hLibModule; // Handle of injected library
char *szDllName = "injdll.dll"; // Library to inject
char *szProcessName = "winlogon.exe"; // Process to inject
/*****************************************
* Load a library into a remote process. *
*****************************************/
int InjectDll()
{
HANDLE hThread; // Thread handle
HANDLE hProcess; // Process handle
DWORD dwPID; // Process ID
char szLibPath[MAX_PATH]; // Full DLL path
void *pLibRemote; // Address (in the remote process) where szLibPath will be copied to
// Enable DEBUG privilege
if (!EnablePrivilege(SE_DEBUG_NAME, TRUE))
return 0;
// Get remote process id
dwPID = GetPIDFromName(szProcessName);
if (dwPID == -1)
return 0;
// Open remote process
hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID);
if (hProcess == NULL)
return 0;
// Get full path of the DLL
if (!GetModuleFileName(hInst, szLibPath, MAX_PATH))
return 0;
strcpy(strrchr(szLibPath, '\\') + 1 , szDllName);
// Allocate memory in the remote process to store the szLibPath string
pLibRemote = VirtualAllocEx(hProcess, NULL, sizeof(szLibPath), MEM_COMMIT, PAGE_READWRITE);
if (pLibRemote == NULL)
return 0;
// Copy the szLibPath string to the remote process.
if (!WriteProcessMemory(hProcess, pLibRemote, (void*)szLibPath, sizeof(szLibPath), NULL))
return 0;
// Load the DLL into the remote process
// (via CreateRemoteThread() & LoadLibrary())
hThread = CreateRemoteThread(hProcess,
NULL,
0,
(LPTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle("Kernel32"), "LoadLibraryA"),
pLibRemote,
0,
NULL);
// Failed
if(hThread == NULL)
{
VirtualFreeEx(hProcess, pLibRemote, sizeof(szLibPath), MEM_RELEASE);
return 0;
}
// Wait for LoadLibrary() to finish and get return code (handle of loaded library)
WaitForSingleObject(hThread, INFINITE);
GetExitCodeThread(hThread, &hLibModule);
CloseHandle(hThread);
CloseHandle(hProcess);
// Free remote memory for szLibPath
VirtualFreeEx(hProcess, pLibRemote, sizeof(szLibPath), MEM_RELEASE);
// Remote LoadLibrary() failed
if (!hLibModule)
return 0;
// Disable DEBUG privilege
EnablePrivilege(SE_DEBUG_NAME, FALSE);
return 1;
}
/****************************************************
* Unload injected library from the remote process. *
****************************************************/
int EjectDll()
{
HANDLE hThread;
HANDLE hProcess;
DWORD dwPID;
DWORD dwRetFreeLibrary;
// Enable DEBUG privilege
if (!EnablePrivilege(SE_DEBUG_NAME, TRUE))
return 0;
// Get remote process id
dwPID = GetPIDFromName(szProcessName);
if (dwPID == -1)
return 0;
// Open remote process
hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID);
if (hProcess == NULL)
return 0;
// Unload the DLL from the remote process
// (via CreateRemoteThread & FreeLibrary)
hThread = CreateRemoteThread(hProcess,
NULL,
0,
(LPTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle("Kernel32"), "FreeLibrary"),
(void*)hLibModule,
0,
NULL );
// Failed to unload
if (hThread == NULL)
return 0;
// Wait for FreeLibrary() to finish and get return code
WaitForSingleObject(hThread, INFINITE);
GetExitCodeThread(hThread, &dwRetFreeLibrary);
CloseHandle(hThread);
CloseHandle(hProcess);
// Disable DEBUG privilege
EnablePrivilege(SE_DEBUG_NAME, FALSE);
return (dwRetFreeLibrary);
}
////////////////////////////////////////////// Inject Code ////////////////////////////////////////
/**************************************************************************************************************
* Some tips when using CreateRemoteThread()/WriteProcessMemory(). *
* *
* 1. Analise generated code. *
* Check injected functions for absolute addressing (calls, jumps, data references, ...) *
* and other generated code that shouldn't be there. *
* Use: *
* A) Project\Settings\C/C++\Listing Files\Listing file type=Assembly, Machine Code, and Source. *
* B) A disassembler (wdasm32). *
* C) A debugger (softice). *
* *
* 2. Turn off stack probes. *
* Check for __chkstk() references in the listing files. *
* A) Use #pragma check_stack(off). [DOESN'T SEEMS TO WORK ?!?] *
* B) Use less than 4K of local variables. *
* C) Augment the stack size: /Gs size (Project\Settings\C/C++\ProjectOptions) *
* *
* 3. Remove the /GZ switch in the debug build. *
* Check for __chkesp() references in the listing files. *
* A) Project\Settings\C/C++\Project Options *
* *
* 4. Disable incremental compilation (/Gi). *
* A) Use #pragma comment(linker, "/INCREMENTAL:NO") *
* B) Remove the /Gi switch (Project\Settings\C/C++\Customize\Enable incremental compilation=Off *
* C) Declare the functions as static. *
* *
* 5. Don't let optimization screw your code. *
* A) Turn off optimization (Project\Settings\C/C++\General\Optimizations=Disable(Debug) *
* B) Use #pragma optimize("", off) *
* C) Don't write functions with the same prototype (e.g. AfterFuncX()). Let them return different values. *
* *
* 6. Split switch() statements in 3 cases maximum, or use if/then/else. *
* *
* 7. Don't call any functions besides those in KERNEL32.LL and USER32.DLL (USER32.DLL isn't garanted to be *
* mapped into every process). *
* Use LoadLibrary()/GetProcAddress if you need functions from other libraries. *
* *
* 8. Don't use any static strings. *
* Pass them in INJDATA. *
* *
* 9. Don't call any function directly. *
* Copy each routine to the remote process individually and supply their addresses in INJDATA. *
* *
* 10. Good luck. *
* If you analise the generated code (using a disassembler) you should catch any errors before executing *
* the code (and crashing the process !). *
**************************************************************************************************************/
#pragma comment(linker, "/INCREMENTAL:NO") // Turns off incremental linking
// Global variables
DWORD PID; // PID of injected process
BYTE *pDataRemote; // Address of INJDATA in the remote process
BYTE *pSASWinProcRemote; // The address of SASWindowProc() in the remote process
#define DUMMY_ADDR 0x12345678 // Dummy addr of INJDATA
// INJDATA: Memory block passed to each remote injected function.
// We pass every function address or string data in this block.
typedef LONG (WINAPI *SETWINDOWLONG) (HWND, int, LONG);
typedef LRESULT (WINAPI *CALLWINDOWPROC) (WNDPROC, HWND, UINT, WPARAM, LPARAM);
typedef HWND (WINAPI *FINDWINDOW) (LPCTSTR, LPCTSTR);
typedef struct {
SETWINDOWLONG fnSetWindowLong; // Addr. of SetWindowLong()
CALLWINDOWPROC fnCallWindowProc; // Addr. of CallWindowProc()
FINDWINDOW fnFindWindow; // Addr. of FindWindow()
char szClassName[50]; // Class name = "SAS Window class"
char szWindowName[50]; // Window name = "SAS window"
HWND hwnd; // Window handle of injected process
WNDPROC fnSASWndProc; // Addr. of remote SASWindowProc
WNDPROC fnOldSASWndProc; // Addr. of old SASWindowProc
} INJDATA, *PINJDATA;
/*****************************************************************
* Subclassed window procedure handler for the injected process. *
*****************************************************************/
#pragma optimize("", off)
#pragma check_stack(off)
static LRESULT CALLBACK SASWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
// INJDATA pointer.
// Must be patched at runtime !
INJDATA* pData = (INJDATA *)DUMMY_ADDR;
if (uMsg == WM_HOTKEY)
{
// Ctrl+Alt+Del
if (lParam == MAKELONG(MOD_CONTROL | MOD_ALT, VK_DELETE))
return 1;
// Ctrl+Shift+Esc
if (lParam == MAKELONG(MOD_CONTROL | MOD_SHIFT, VK_ESCAPE))
return 1;
}
// Call the original window procedure
return pData->fnCallWindowProc(pData->fnOldSASWndProc, hwnd, uMsg, wParam, lParam);
}
static int AfterSASWindowProc(void) {return 1;}
/*************************************************
* Subclass the remote process window procedure. *
* Return: 0=failure, 1=success *
*************************************************/
#pragma optimize("", off)
#pragma check_stack(off)
static DWORD WINAPI InjectFunc (INJDATA *pData)
{
// Subclass window procedure
pData->fnOldSASWndProc = (WNDPROC) pData->fnSetWindowLong (pData->hwnd, GWL_WNDPROC, (long)pData->fnSASWndProc);
return (pData->fnOldSASWndProc != NULL);
}
static int AfterInjectFunc(void) {return 2;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -