Cogitations poenam nemo patitur (лат.)
Никто не несет наказания за мысли
© sysenter 2006
JID: sysenter@jabber.no
Теперь о памяти и динамических библиотеках в нативе
Дергаем функцию из любой библиотеки:
Как Вы понимаете, здесь:Код (C++):
bool WINAPI GetProcAdrLibFunc(wchar_t* wcLibName, wchar_t* pFunc ,char* FunName,WORD Ordinal) { UNICODE_STRING wmP; HMODULE NTDLL; if(!NTDLL) { RtlInitUnicodeString(&wmP,wcLibName); if((!NT_SUCCESS(LdrGetDllHandle(0,0,&wmP,&NTDLL)))|| NTDLL==NULL) if(!NT_SUCCESS(LdrLoadDll(NULL,0,&wmP,&NTDLL))) {*pFunc=NULL;return false;} RtlFreeUnicodeString(&wmP); } if(FunName!=NULL) { ANSI_STRING wmPP; RtlInitAnsiString(&wmPP,FunName); if((!NT_SUCCESS(LdrGetProcedureAddress(NTDLL,&wmPP,Ordinal,(PVOID*)pFunc)))|| *pFunc==NULL){*pFunc=NULL;return false;} RtlFreeAnsiString(&wmPP); } else { if((!NT_SUCCESS(LdrGetProcedureAddress(NTDLL,NULL,Ordinal,(PVOID*)pFunc)))|| *pFunc==NULL){*pFunc=NULL;return false;} } return true; }
wcLibName ― имя библиотеки в юникоде;
pFunc ― полученный после отработки указатель на функцию (результат);
FunName ― имя функции которую вам нужно найти или если угодно можете искать по Ordinal, тогда имя должно быть NULL.
Идем далее... Вдруг мы захотели выгрузить какую либо dll в любом процессе... Тогда делаеам следующее:Здесь все происходит с таймаутом (NtDelayExecution), как видите. Суть ― во внедрении шелкода в чужой процесс вызовом его, потом ожидаем и вызывается в нем LdrUnloadDll.Код (C++):
typedef struct _INJECT_CODE //С отложенной загрузкой через Sleep { DWORD PushCommand0; /*0,1,2,3*/ DWORD SleepTimeAdr; /*4,5,6,7*/ DWORD PushAndBYTE; /*8,9,A,B*/ DWORD CallComand0; /*C,D,E,F*/ DWORD CallAddr0; /*10,11,12,13*/ DWORD PushCommand1; /*14,15,16,17*/ DWORD ModuleHandle; /*18,19,1A,1B*/ DWORD CallCommand; /*1C,1D,1E,1F*/ DWORD CallAddr; /*20,21,22,23*/ DWORD PushCommand5; /*24,25,26,27*/ DWORD ExitCode; /*28,29,2A,2B*/ DWORD CallCommand2; /*2C,2D,2E,2F*/ DWORD CallExAddr; /*30,31,32,33*/ DWORD AddrUnLoadLibrary; /*34,35,36,37*/ DWORD dlH; /*38,39,3A,3B*/ DWORD AddrExitThread; /*3C,3D,3E,3F*/ DWORD AddrSleep; /*40,41,42,43*/ DWORD SleepTimeLow; /*44,45,46,47*/ DWORD SleepTimeHi; /*48,49,4A,4B*/ } INJECT_CODE, *PINJECT_CODE; bool DelayUnloadDll(HANDLE PID, DWORD DllBase, DWORD DelayLoadTime) { CLIENT_ID ClientId; OBJECT_ATTRIBUTES ObjAttr; InitializeObjectAttributes(&ObjAttr, NULL, 0, NULL, NULL); HANDLE handle=NULL; ClientId.UniqueProcess =PID; ClientId.UniqueThread =LongToHandle(0); if(NT_SUCCESS(NtOpenProcess(&handle,PROCESS_ALL_ACCESS,&ObjAttr,&ClientId)) && handle!=NULL) { LPVOID Mem=NULL; SIZE_T RegionSize=sizeof(INJECT_CODE); if(NT_SUCCESS(NtAllocateVirtualMemory(handle,&Mem,0x00000000,&RegionSize,MEM_COMMIT,PAGE_EXECUTE_READWRITE))) { DWORD M=(DWORD)Mem; if(Mem==NULL) return false; INJECT_CODE Inject; if(GetProcAdrLibFunc((PVOID*)&Inject.AddrUnLoadLibrary,"LdrUnloadDll",0) && GetProcAdrLibFunc((PVOID*)&Inject.AddrExitThread,"RtlExitUserThread",0) && GetProcAdrLibFunc((PVOID*)&Inject.AddrSleep,"NtDelayExecution",0)) { Inject.PushCommand0=0x68909090; Inject.SleepTimeAdr=M+0x44;//DelayLoadTime; Inject.PushAndBYTE =0x006A9090; Inject.CallComand0=0x15FF9090; Inject.CallAddr0=M+0x40; Inject.PushCommand1=0x68909090; //puch xxxx Inject.ModuleHandle=DllBase; Inject.CallCommand=0x15FF9090; //call [xxxx]10000* Inject.CallAddr=M+0x34; Inject.PushCommand5=0x68909090; Inject.ExitCode=NULL; Inject.CallCommand2=0x15FF9090; Inject.CallExAddr=M+0x3C; Inject.dlH=DllBase; Inject.SleepTimeLow=-10000*DelayLoadTime; Inject.SleepTimeHi=0xFFFFFFFF; if(NT_SUCCESS(NtWriteVirtualMemory(handle,Mem,(LPCVOID)&Inject,sizeof(INJECT_CODE),NULL))) { HANDLE hrT=NULL; CLIENT_ID ClientId; if(NT_SUCCESS(RtlCreateUserThread(handle,NULL,TRUE,0,0,0,(PRTL_THREAD_START_ROUTINE)Mem,NULL,&hrT,&ClientId))) { if(hrT!=NULL) { struct { SCSRSSPORT_MESSAGE PortMessage; CSRSS_MESSAGE CsrssMessage; THREAD_INFO ThreadInfo; }csrmsg = {{0},{0},{hrT, ClientId}}; CsrClientCallServer(&csrmsg,0,0x10001,0x0C); NtResumeThread(hrT,NULL); NtWaitForSingleObject(hrT,FALSE,NULL); if(!F_SOFT) { NTSTATUS sta=NtUnmapViewOfSection(handle,(LPVOID)DllBase); sta=NtFreeVirtualMemory(handle,(PVOID*)&DllBase,&((SIZE_T)LastSize),MEM_DECOMMIT | MEM_RELEASE); } RegionSize=sizeof(INJECT_CODE); NtFreeVirtualMemory(handle,&Mem,&RegionSize,MEM_DECOMMIT); NtClose(handle); return true; } else OutputDebugString("Error:RtlCreateUserThread Handle=NULL"); } else OutputDebugString("Error:RtlCreateUserThread"); NtFreeVirtualMemory(handle,&Mem,&RegionSize,MEM_DECOMMIT); } else OutputDebugString("Error:NtWriteVirtualMemory"); } else OutputDebugString("Error:GetProcAdrLibFunc"); } else OutputDebugString("Error:NtAllocateVirtualMemory"); } else OutputDebugString("Error:NtOpenProcess (PROCESS_ALL_ACCESS)"); NtClose(handle); return false; }
Работало на ХР и вин7, возможно, хардкодес о уведомлении сервера подсистемы может и не сработать CsrClientCallServer. Не проверялось дальше, возможно флаги поменялись у CsrClientCallServer. Но, вроде бы, работает. Кстати, при выгрузке чужой dll, не забываем предварительно получить привилегии отладчика. (см. часть 2 про драйвера).
Для любителей натива (часть 3) Работа с dll
Дата публикации 9 янв 2018
| Редактировалось 24 янв 2018