1. Если вы только начинаете программировать на ассемблере и не знаете с чего начать, тогда попробуйте среду разработки ASM Visual IDE
    (c) на правах рекламы
    Скрыть объявление

Для любителей натива (часть 3) Работа с dll

Дата публикации 9 янв 2018 | Редактировалось 24 янв 2018
Cogitations poenam nemo patitur (лат.)
Никто не несет наказания за мысли
© sysenter 2006

JID: sysenter@jabber.no

Теперь о памяти и динамических библиотеках в нативе


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

0 1.289
RET

RET
Well-Known Member

Регистрация:
5 янв 2008
Публикаций:
17