Remove the DLL from the process module list and keep it running normally. This is simple to think about. byshell was used long ago,
The simple idea is to copy the current dll Memory image, jump to the code of the copied address space, and free up the original DLL,
Immediately use virtualalloc to apply for a block of the same size on the original base address, copy the block back, and then jump back for execution. .
After the code is written, the application in the actual program will find the problem. Once malloc or new is called, it will crash,
So I checked the byshell code and found that the applied memory uses virtualalloc, but a lot of my code is allocated with new, and it is difficult to use virtualalloc to allocate class objects ~
After adjustment, it is clear that every DLL and windows will allocate a heap to it,
In freelibrary, the system will completely destroy it, not afraid of your memory leakage.
During debugging, The heapdestroy breakpoint is triggered exactly once after freelibrary, that is, the heap is destroyed.
The solution is to change the first command of heapdestroy to return before freelibrary, and then fix it again.
Practice has proved stable ......
*/
# Include <windows. h>
# Include <stdio. h>
# Include <tlhelp32.h>
# Include <psapi. h>
# Pragma comment (Lib, "psapi. lib ")
# DEFINE _ printf
Void hidelibrary (hmodule, lpvoid pcallbackaddr, lpvoid lparam );
Typedef struct
{
Hmodule lpdllbase;
Lpvoid lpnewdllbase;
Pthread_start_routine paddress;
Lpvoid lparam;
} Unloadlib_callback, * punloadlib_callback;
Typedef
Lpvoid winapi virtualalloc (
Lpvoid lpaddress,
Size_t dwsize,
DWORD flallocationtype,
DWORD flprotect
);
Typedef
Bool winapi virtualfree (
Lpvoid lpaddress,
Size_t dwsize,
DWORD dwfreetype
);
Typedef
Bool winapi heapdestroy (
Handle hheap
);
Typedef
Hmodule winapi loadlibrary (
Lptstr lpfilename
);
Typedef
Handle winapi createthread (
Lpsecurity_attributes lpthreadattributes,
Size_t dwstacksize,
Lpthread_start_routine lpstartaddress,
Lpvoid lpparameter,
DWORD dwcreationflags,
Lpdword lpthreadid
);
Typedef void * _ cdecl memcpy (void *, const void *, size_t );
Bool inclibrarycount (hmodule HME)
{
// After freelibrary, many system DLL files will also be free, so load all loaded files again to increase the count.
Handle hmodssnap = createconlhelp32snapshot (th32cs_snapmodule, 0 );
If (invalid_handle_value = hmodssnap)
{
Return false;
}
Moduleentry32 memoduleentry;
Memoduleentry. dwsize = sizeof (moduleentry32 );
If (! Module32first (hmodssnap, & memoduleentry ))
{
Closehandle (hmodssnap );
Return false;
}
Do
{
If (loadlibrary (memoduleentry. szmodule) = HME)
Freelibrary (HME );
} While (module32next (hmodssnap, & memoduleentry ));
Closehandle (hmodssnap );
Return true;
}
// Enumerate all threads of a specified process
DWORD winapi enumandsetthreadstate (lpvoid lparam)
{
Handle hthreadsnap = NULL;
Threadentry32 te32;
Memset (& te32, 0, sizeof (te32 ));
Te32.dwsize = sizeof (threadentry32 );
Hthreadsnap = createconlhelp32snapshot (th32cs_snapthread, 0 );
DWORD mythreadid = getcurrentthreadid ();
DWORD pid = getcurrentprocessid ();
If (thread32first (hthreadsnap, & te32 ))
{
Do
{
If (pid = te32.th32ownerprocessid)
{
If (mythreadid! = Te32.th32threadid)
{
Handle hthread = openthread (
Thread_suspend_resume,
False,
Te32.th32threadid );
If (hthread! = NULL)
{
If (INT) lparam)
Resumethread (hthread );
Else
Suspendthread (hthread );
Closehandle (hthread );
}
}
}
}
While (thread32next (hthreadsnap, & te32 ));
}
Closehandle (hthreadsnap );
Return 0;
}
DWORD winapi gotocallbackaddr (lpvoid lparam)
{
Punloadlib_callback cbfunc = (punloadlib_callback) lparam;
DWORD dwthreadid;
Handle hthread;
If (cbfunc-> paddress)
{
Hthread = createthread (
Null,
0,
Cbfunc-> paddress,
Cbfunc-> lparam,
0,
& Dwthreadid );
If (hthread)
Closehandle (hthread );
}
// The DLL copy is not required. Release ~
Virtualfree (cbfunc-> lpnewdllbase, 0, mem_decommit );
Delete cbfunc;
Return 0;
}
DWORD winapi unloadlibrary (lpvoid lparam)
{
// _ Asm int 3
_ Printf ("unloadlibrary entry. \ r \ n ");
Byte heapdestroy_hookcode_bak [4];
Byte heapdestroy_hookcode [4] = "\ xc2 \ x04 \ x00"; // retn 0004
Moduleinfo modinfo;
DWORD oldprotect;
Punloadlib_callback cbfunc = (punloadlib_callback) lparam;
Hmodule hdllinstance = cbfunc-> lpdllbase;
Char dllpath_bak [max_path];
Getmodulefilename (hdllinstance, dllpath_bak, sizeof (dllpath_bak ));
Getmoduleinformation (getcurrentprocess (), hdllinstance, & modinfo, sizeof (moduleinfo ));
// Increase the count for all the DLL files (except the DLL files) to prevent the DLL files from being detached from the system during freelibrary.
Inclibrarycount (hdllinstance );
// For the sake of insurance, suspend other threads and resume after completing the measures
Enumandsetthreadstate (lpvoid) False );
// After freelibrary, the memory originally stored in the API address will also be released,
// However, there are still some actions after freelibrary. If there is no free operation yet, write down the key APIs.
Virtualalloc * _ virtualalloc = (virtualalloc *)
Getprocaddress (getmodulehandle ("kernel32.dll"), "virtualalloc ");
Loadlibrary * _ loadlibrary = (loadlibrary *)
Getprocaddress (getmodulehandle ("kernel32.dll"), "loadlibrarya ");
Createthread * _ createthread = (createthread *)
Getprocaddress (getmodulehandle ("kernel32.dll"), "createthread ");
Memcpy * _ memcpy = (memcpy *)
Getprocaddress (getmodulehandle ("NTDLL. dll"), "memcpy ");
// This is very important. It is not called by me. It is called by the system when freelibrary is used. I want to hook it,
// The heap cannot be damaged to the system. Otherwise, the subsequent dll may work,
// However, you cannot use new or malloc to apply for memory. virtualalloc can be used instead,
// However, If you rewrite a lot of code, it is not possible, and some code is not easy to modify, such as the new
Heapdestroy * _ heapdestroy = (heapdestroy *)
Getprocaddress (getmodulehandle ("kernel32.dll"), "heapdestroy ");
Virtualprotect (_ heapdestroy, 3, page_execute_readwrite, & oldprotect );
// Modify the first command to return directly
_ Memcpy (heapdestroy_hookcode_bak, _ heapdestroy, 3 );
_ Memcpy (_ heapdestroy, heapdestroy_hookcode, 3 );
// Sleep (1, 100 );
// It's finally here ~~~ ^_^!
Freelibrary (hdllinstance); // release
// Fixed the hook function.
_ Memcpy (_ heapdestroy, heapdestroy_hookcode_bak, 3 );
// _ Memcpy (_ rtlfreeheap, rtlfreeheap_hookcode_bak, 3 );
// Apply for the same size of memory at the original DLL base address, and copy the previous DLL back
If (_ virtualalloc (hdllinstance,
Modinfo. sizeofimage,
Mem_commit | mem_reserve,
Page_execute_readwrite) = NULL
)
{
// Failed. Load the original DLL and work normally
// Note: Do not call hidelibrary in dllmain. loadlibrary will cause dllmain to be called again, leading to an endless loop.
Hmodule hdll = _ loadlibrary (dllpath_bak );
// Recalculate the address of the callback function in the hdll address space
Cbfunc-> paddress = (lpthread_start_routine)
(DWORD) cbfunc-> paddress-(DWORD) hdllinstance + (DWORD) hdll );
Lpthread_start_routine pfunc1 = (lpthread_start_routine)
(DWORD) enumandsetthreadstate-(DWORD) hdllinstance + (DWORD) hdll );
// Resume the suspended thread
_ Createthread (0, 0, pfunc1, (lpvoid) True, 0, 0 );
// Call the callback function
If (cbfunc-> paddress)
_ Createthread (0, 0, cbfunc-> paddress, cbfunc-> lparam, 0, 0 );
Return 0;
}
_ Memcpy (hdllinstance, cbfunc-> lpnewdllbase, modinfo. sizeofimage );
// Resume the suspended thread
Enumandsetthreadstate (lpvoid) True );
// Jump back to the gotocallbackaddr of the original DLL address space to release the pointer applied by virtualalloc.
_ Createthread (0, 0, gotocallbackaddr, cbfunc, 0, 0 );
Return 0;
}
DWORD winapi hidelibrary02 (lpvoid lparam)
{
// _ Asm int 3
_ Printf ("hidelibrary02 entry. \ r \ n ");
Punloadlib_callback cbfunc = (punloadlib_callback) lparam;
Moduleinfo modinfo;
Getmoduleinformation (getcurrentprocess (), cbfunc-> lpdllbase, & modinfo, sizeof (moduleinfo ));
// Apply for a memory of the same size as the current DLL
Cbfunc-> lpnewdllbase = virtualalloc (null, modinfo. sizeofimage, mem_commit | mem_reserve, page_execute_readwrite );
If (cbfunc-> lpnewdllbase = NULL)
Return false;
// Copy the current DLL and copy all the data to the applied memory,
Memcpy (cbfunc-> lpnewdllbase, modinfo. lpbaseofdll, modinfo. sizeofimage );
// Calculate the unloadlibrary address in copy and execute the code from another thread to this address.
Void * pnewunloadlibrary = lpvoid (DWORD) cbfunc-> lpnewdllbase + (DWORD) unloadlibrary-(DWORD) modinfo. lpbaseofdll );
DWORD threadid;
Handle hthread = createthread (0, 0,
(Lpthread_start_routine) pnewunloadlibrary, (lpvoid) cbfunc, create_suincluded, & threadid );
If (hthread = NULL)
{
Virtualfree (cbfunc-> lpnewdllbase, 0, mem_decommit );
Delete cbfunc;
Return false;
}
Resumethread (hthread );
Closehandle (hthread );
Return true;
}
Void hidelibrary (hmodule, lpvoid pcallbackaddr, lpvoid lparam)
{
_ Printf ("hidelibrary entry. \ r \ n ");
Punloadlib_callback lparam = new unloadlib_callback;
Lparam-> lpdllbase = hmodule;
Lparam-> lpnewdllbase = NULL;
Lparam-> paddress = (pthread_start_routine) pcallbackaddr;
Lparam-> lparam = lparam;
Handle hthread = createthread (0, 0,
Hidelibrary02, (lpvoid) lparam, 0, null );
If (hthread = NULL)
{
_ Printf ("createthread hidelibrary02 failed. \ r \ n ");
Delete lparam;
Return;
}
Closehandle (hthread );
Return;
}
//////////////////////////////////////// ///////////////////
// Example
// Rundll32 unloadlibrary. dll, test
DWORD winapi testthread (lpvoid lparam)
{
Char * Ptest = new char [512];
Sprintf (Ptest, "My PID: % d \ r \ n can't find this DLL in some software? ", Getcurrentprocessid ());
MessageBox (0, Ptest, (char *) lparam, 0 );
Delete Ptest;
Return 0;
}
DWORD winapi testthread02 (lpvoid lparam)
{
Hmodule = (hmodule) lparam;
Char * Ptest = new char [512];
Sprintf (Ptest, "testthread02 \ r \ n ");
Sleep (500 );
MessageBox (0, Ptest, "Start", 0 );
// If the callback function is not set, the success is fine. If the callback function fails, gameover
Hidelibrary (hmodule, 0, 0 );
Sprintf (Ptest, "My PID: % d \ r \ n can't find this DLL in some software? ", Getcurrentprocessid ());
MessageBox (0, Ptest, "OK", 0 );
Delete Ptest;
Return 0;
}
Hmodule hdll;
Extern "C"
{
_ Declspec (dllexport) int test ();
}
Int test ()
{
// 1
// After the main thread starts to work, hidelibrary is not safe.
// Createthread (0, 0, testthread02, hdll, 0, 0 );
//
// 2
// Properly enable the main working thread after the DLL is released
Char * P = strdup ("hello ");
Hidelibrary (hdll, testthread, P );
Sleep (60000 );
Return 0;
}
Bool apientry dllmain (handle hmodule,
DWORD ul_reason_for_call,
Lpvoid lpreserved
)
{
Switch (ul_reason_for_call)
{
Case dll_process_attach:
{
Hdll = (hmodule) hmodule;
}
Break;
}
Return true;
}