2011-01-28 5 views
2

Je suis en train de créer un programme de sécurité pour mon réseau. Une de ses instances est de vérifier et de surveiller ce que les API et les bibliothèques sont appelés. La DLL pour faire cela et le programme qui va avec sont déjà finis. Mais il y a un problème que je n'arrive pas à résoudre. Lorsque j'essaie d'injecter ma DLL dans des processus système (tels que explorer.exe, mon processus de système de test principal) avec NtCreateThreadEx, j'obtiens la valeur de retour: C0000022, cela signifie quelque chose comme: Status_Access_Denied (il retourne dans NTSTATUS , mais DWORD fera)Dll injection injection

Je ne sais pas quoi faire, je suis en cours d'exécution en tant qu'administrateur, je levais les privilèges, et utilisé les fonctions appropriées, je reçois toujours c0000022

Voici le code que je suis utiliser pour injecter (impossible d'afficher le code ici, car la barre d'outils n'apparaîtra pas)

#include "main.h" 

typedef DWORD NTSTATUS; 

struct NtCreateThreadExBuffer{ 
ULONG Size; 
ULONG Unknown1; 
ULONG Unknown2; 
PULONG Unknown3; 
ULONG Unknown4; 
ULONG Unknown5; 
ULONG Unknown6; 
PULONG Unknown7; 
ULONG Unknown8; 
}; 


typedef NTSTATUS (WINAPI *LPFUN_NtCreateThreadEx) 
(
OUT PHANDLE hThread, 
IN ACCESS_MASK DesiredAccess, 
IN LPVOID ObjectAttributes, 
IN HANDLE ProcessHandle, 
IN LPTHREAD_START_ROUTINE lpStartAddress, 
IN LPVOID lpParameter, 
IN BOOL CreateSuspended, 
IN ULONG StackZeroBits, 
IN ULONG SizeOfStackCommit, 
IN ULONG SizeOfStackReserve, 
OUT LPVOID lpBytesBuffer 
); 

using namespace std; 

//#define CREATE_THREAD_ACCESS (PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ) 
#define CREATE_THREAD_ACCESS (PROCESS_ALL_ACCESS) 

BOOL LoadDll(char *procName, char *dllName); 
BOOL InjectDLL(DWORD dwProcessID, char *dllName); 

BOOL LoadDll(char *dllName, DWORD dwProcID){ 

printf("Process Id to Inject: %d",dwProcID); 

if(!dwProcID){ 
    printf("No vailid PID\n"); 
    return false; 
} 

FILE* FileCheck = fopen(dllName, "r"); 

if(FileCheck==NULL){ 
printf("\nUnable to inject %s", dllName); 
return false; 
} 

fclose(FileCheck); 


if(!InjectDLL(dwProcID, dllName)){ 

    printf("injection failed\n"); 
return false; 
} else { 
return true; 
} 

} 



BOOL InjectDLL(DWORD dwProcessID, char *dllName){ 

HANDLE hProc; 
HANDLE hToken; 
char buf[50]={0}; 
LPVOID RemoteString, LoadLibAddy; 

if(!dwProcessID)return false; 


HANDLE hCurrentProc = GetCurrentProcess(); 

if (!OpenProcessToken(hCurrentProc,TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES,&hToken)){ 

printf("OpenProcessToken Error:%d\n", GetLastError()); 


} else { 

if (!RaisePrivleges(hToken, (char*)SE_DEBUG_NAME)){ 

    printf("SetPrivleges SE_DEBUG_NAME Error:%d\n", GetLastError()); 


} 

} 


if (hToken)CloseHandle(hToken); 

hProc = OpenProcess(CREATE_THREAD_ACCESS, FALSE, dwProcessID); 

printf("\nHandle to process: %x\n", hProc); 

if(!hProc){ 

printf("OpenProcess() failed: %d", GetLastError()); 
return false; 

} 

LoadLibAddy = (LPVOID)GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA"); 


if(!LoadLibAddy){ 

printf("GetProcAddress() failed: %d", GetLastError()); 
return false; 

} 

RemoteString = (LPVOID)VirtualAllocEx(hProc, NULL, strlen(dllName), MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE); 

if(RemoteString == NULL){ 

printf("VirtualAllocEx() failed: %d", GetLastError()); 
return false; 

} 


printf("\nRemote address: %x\n", RemoteString); 

if(WriteProcessMemory(hProc, (LPVOID)RemoteString, dllName, strlen(dllName), NULL) == NULL){ 

printf("WriteProcessMemory() failed: %d", GetLastError()); 
return false; 

} 

/* 
if(!CreateRemoteThread(hProc, NULL, NULL, (LPTHREAD_START_ROUTINE)LoadLibAddy, (LPVOID)RemoteString, NULL, NULL)){ 

    printf("CreateRemoteThread() failed: %d", GetLastError()); 
    return false; 

} 
*/ 

HMODULE modNtDll = GetModuleHandle("ntdll.dll"); 


if(!modNtDll) 
{ 
printf("n failed to get module handle for ntdll.dll, Error=0x%.8x", GetLastError()); 
return 0; 
} 

LPFUN_NtCreateThreadEx funNtCreateThreadEx = 
(LPFUN_NtCreateThreadEx) GetProcAddress(modNtDll, "NtCreateThreadEx"); 


if(!funNtCreateThreadEx) 
{ 
printf("n failed to get function (NTCreateThreadEx) address from ntdll.dll, Error=0x%.8x\nTrying CreateRemoteThread api\n", GetLastError()); 

if(!CreateRemoteThread(hProc, NULL, NULL, (LPTHREAD_START_ROUTINE)LoadLibAddy, (LPVOID)RemoteString, NULL, NULL)){ 

    printf("CreateRemoteThread() failed: %d", GetLastError()); 
    return false; 

} else { 
printf("CreateRemoteThread success!\n"); 
return true; 
} 


return 0; 
} 


NtCreateThreadExBuffer ntbuffer; 

memset (&ntbuffer,0,sizeof(NtCreateThreadExBuffer)); 
DWORD temp1 = 0; 
DWORD temp2 = 0; 
HANDLE pRemoteThread = NULL; 

ntbuffer.Size = sizeof(NtCreateThreadExBuffer); 
ntbuffer.Unknown1 = 0x10003; 
ntbuffer.Unknown2 = 0x8; 
ntbuffer.Unknown3 = &temp2; 
ntbuffer.Unknown4 = 0; 
ntbuffer.Unknown5 = 0x10004; 
ntbuffer.Unknown6 = 4; 
ntbuffer.Unknown7 = &temp1; 
ntbuffer.Unknown8 = 0; 

NTSTATUS status = funNtCreateThreadEx(
&pRemoteThread, 
0x1FFFFF, 
NULL, 
hProc, 
(LPTHREAD_START_ROUTINE) LoadLibAddy, 
(LPVOID)RemoteString, 
FALSE, //start instantly 
NULL, 
NULL, 
NULL, 
&ntbuffer 
); 

printf("NTCreateThreadEx return: %x\n", status); 

// Resume the thread execution 

WaitForSingleObject(pRemoteThread, INFINITE); 


//Check the return code from remote thread function 
DWORD dwExitCode; 
if(GetExitCodeThread(pRemoteThread, (DWORD*) &dwExitCode)) 
{ 
    printf("\n Remote thread returned with status = %d\n", dwExitCode); 
} 


CloseHandle(pRemoteThread); 


CloseHandle(hProc); 
return true; 

} 


BOOL RaisePrivleges(HANDLE hToken, char *pPriv){ 

TOKEN_PRIVILEGES tkp; 
tkp.PrivilegeCount = 1; 
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 
tkp.Privileges[0].Luid.HighPart = 0; 
tkp.Privileges[0].Luid.LowPart = 0; 

if (!LookupPrivilegeValue(NULL, pPriv, &tkp.Privileges[0].Luid)){ 

printf("LookupPrivilegeValue Error:%d\n", GetLastError()); 
return FALSE; 

} 

int iRet = AdjustTokenPrivileges(hToken, FALSE, &tkp, 0x10, (PTOKEN_PRIVILEGES)NULL, 0); 

if (iRet == NULL){ 

printf("AdjustTokenPrivileges Error:%d\n", GetLastError()); 
return TRUE; 

} else { 

iRet = GetLastError(); 

switch (iRet){ 

case ERROR_NOT_ALL_ASSIGNED:{ 
printf("AdjustTokenPrivileges ERROR_NOT_ALL_ASSIGNED\n"); 
return FALSE; 
     } 

case ERROR_SUCCESS:{ 
return TRUE; 
     } 
default:{ 
printf("AdjustTokenPrivileges Unknow Error:%d\n", iRet); 
return FALSE; 
    } 
} 
} 
} 
+0

Je voulais éditer votre question pour ajouter votre code directement dans la question mais c'est ** trop long **! Est-ce que vous vous attendez vraiment à ce que quelqu'un passe en revue tout votre code?! – ereOn

+0

Non, je ne suis pas, en fait ce code fonctionne très bien, pas d'erreurs et pas de problèmes jusqu'à ce que j'essaie d'injecter du code dans les processus du système. Dans d'autres applications, cela fonctionne bien. – Unknown

+2

Le problème est que cette question sera ici encore (et consultable par google) après que pastbin a disparu depuis longtemps. – Flexo

Répondre

2

1) Si vous utilisez VISTA ou plus tard, vous essayez d'injecter dans un «processus protégé» à partir d'un «processus non protégé». Voir Process Security and Access Rights dans MSDN. Les processus non protégés ne peuvent pas créer de threads dans les processus protégés. bien que je doive admettre que je m'attendrais à l'appel d'ouvrir le processus à l'échec lorsque vous demandez les droits d'accès inappropriés plutôt que l'appel de thread de créer subséquent pour échouer.

2) Pourquoi utilisez-vous NtCreateThreadEx() plutôt que d'appeler simplement CreateRemoteThread()?

3) Ce n'est probablement pas la cause de votre problème, mais ... Vous ne parvenez pas à allouer de la mémoire pour le terminateur null dans la chaîne, vous devez allouer strlen(dllName) + 1.

4) Je suppose que le processus qui effectue l'injection et le processus dans lequel vous injectez sont à la fois la même architecture, vous n'exécutez pas un x86 exe sur x64 et vous vous attendez à injecter dans un x64 exe?

+0

1: Je cours une version de Windows plus tard que Vista, mais comment est-ce que je devrais me débrouiller alors? J'ai lu qu'il était possible d'injecter du code dans des processus protégés avec NTCreateThread (réponse 3) Peut-être que ce n'est pas possible de cette façon ... Mais là encore, comment faire fonctionner mon code dans un processus protégé. Avez-vous des suggestions? Aussi pourquoi ne fonctionne-t-il pas dans Windows XP? – Unknown

+0

Je suggère que vous l'obteniez fonctionnant, avec CreateRemoteThread() sur XP d'abord. Je suppose que cela fonctionne de manière fiable pour les processus «normaux»? Qu'en est-il de la réponse à 4 et le code fonctionne-t-il différemment une fois que vous avez corrigé le bug détaillé en 3? –

+0

J'ai regardé dans un débogueur et l'allocation n'est pas un problème tout tient dans un joli tampon initialisé 0. le dll est 32 bits et fonctionne normalement sur les deux systèmes x64 et x86 mais pas sur les processus du système, je vais cependant vérifier double – Unknown

1

Puisqu'il est difficile de trouver la bonne réponse à ce problème, je poste même si le fil est vieux. J'essayais d'injecter dans le service x64 sur Win7 x64 et continuais à rencontrer les mêmes problèmes. Ma solution était:

  1. Compiler à la fois l'injecteur et la dll d'injection sous la forme de x64.
  2. Au lieu de CreateRemoteThread & NtCreateThreadEx (tous deux ayant échoué) utilisent RtlCreateUserThread.