#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <tlhelp32.h>
#define USAGE "./%s <process> <nameDll>\n\n"

int DechargerDll(char* nomDll,char* process);
long NomProcessusToPid(char* process);
HANDLE TrouverHandleDllProcess(char* nameDll);

int main(int argc , char* argv[] )
{
    FreeLibrary(NULL);
    printf("Unload fucking dll par 0vercl0k.\n\n");
    if(!argv[1] || !argv[2]){printf(USAGE,argv[0]); return 0;}
    DechargerDll(argv[2],argv[1]);

}

long NomProcessusToPid(char* process)
{
    HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
    PROCESSENTRY32 structprocsnapshot = {0};

    structprocsnapshot.dwSize = sizeof(PROCESSENTRY32);

    if(snapshot == INVALID_HANDLE_VALUE)return 0;
    if(Process32First(snapshot,&structprocsnapshot) == FALSE)return 0;

    while(Process32Next(snapshot,&structprocsnapshot) )
    {
       if(!strcmp(structprocsnapshot.szExeFile,process))
       {
            CloseHandle(snapshot);
            return structprocsnapshot.th32ProcessID;
       }
    }
    CloseHandle(snapshot);
    return 0;
}

HANDLE TrouverHandleDllProcess(char* nameDll,long pid)
{
    HANDLE snapshotModule = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE,pid);
    MODULEENTRY32 structmodsnapshot = {0};

    structmodsnapshot.dwSize = sizeof(MODULEENTRY32);

    if(snapshotModule == INVALID_HANDLE_VALUE)return 0;
    if(Module32First( snapshotModule , &structmodsnapshot ) == FALSE)return 0;

    while(Module32Next(snapshotModule , &structmodsnapshot))
    {
        if(!strcmp(structmodsnapshot.szModule,nameDll))
        {
            CloseHandle(snapshotModule);
            return structmodsnapshot.hModule;
        }
    }
    CloseHandle(snapshotModule);
    return NULL;
}

int DechargerDll(char* nomDll,char* process)
{
    long pidProc = NomProcessusToPid(process);
    HANDLE handleProcess = OpenProcess( PROCESS_ALL_ACCESS , FALSE , pidProc );
    HANDLE handleDllParametre = TrouverHandleDllProcess(nomDll,pidProc);

    if(handleProcess == NULL  || handleDllParametre == NULL){printf("[!]OpenProcess || Dll inexistante ?\n");return 0;}

    DWORD identThread;
    LPTHREAD_START_ROUTINE addrFreeLibrary = (LPTHREAD_START_ROUTINE)GetProcAddress(LoadLibrary("kernel32"),"FreeLibrary");
    HANDLE retourFonctionRemoteThread = CreateRemoteThread( handleProcess , NULL , 0 , addrFreeLibrary , handleDllParametre , 0 , &identThread );
    if(retourFonctionRemoteThread == NULL){printf("[!]CreateRemoteThread\n");return 0;}

    WaitForSingleObject(retourFonctionRemoteThread,INFINITE);

    CloseHandle(retourFonctionRemoteThread);
    CloseHandle(handleDllParametre);
    CloseHandle(handleProcess);
    printf("[+]Unload avec succes.\n");
}