一个向别的进程插入dll的代码

本文介绍了一种使用调试API和内存操作技术将DLL注入目标进程的方法。通过创建子进程并设置断点,可以在适当时机调用特定函数实现DLL的注入。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 --------- Functions in C ---------------

CONTEXT OriginalContext; //Get/SetThreadContext's parameter
char OriginalCodePage[4096];
DWORD sizeofCP=0;
VOID* mySec; //my section...Offset of CodePage in the target process's memory, not this app's memory

BOOL InjectDLL_CreateProcess( char *TargetAPP, char *DLLTOINJECT )
{
   BOOL B=FALSE, BREAK1=FALSE, BREAK2=FALSE;
   STARTUPINFO          sInfo;
   PROCESS_INformATION pInfo;
   DEBUG_EVENT          dEvent;
   DWORD              ret;
   
   ZeroMemory((VOID*)&sInfo, sizeof(sInfo));

   B = CreateProcess(Filename, 0, 0, 0, FALSE, DEBUG_ONLY_THIS_PROCESS, 0, 0, &sInfo, &pInfo);
   if(!B) return FALSE;
   
   //-----
   ///
     
   / We need 3 things, ProcessHandle, ThreadHandle, and BaseOfImage (base address of executable file in memory)
     
   ///
   //-----


   HANDLE              PHandle=pInfo.hProcess, THandle=pInfo.hThread; // Processhandle, Thread handle
   VOID *              BaseOfImage;
   char              DLLTOINJECT[] = "d://VCPrj//MSNInject//DLL//Release//DLL.dll";

   while(1)
   {
      if( !(B = WaitForDebugEvent(&dEvent, INFINITE)) ) //Remember? -- dEvent is a structure that recv'es return of fucntion
          return -1;
      
      if(dEvent.dwDebugEventCode==CREATE_PROCESS_DEBUG_EVENT)  //If the debug event was "Process has just been created"
      {
          BaseOfImage = dEvent.u.CreateProcessInfo.lpBaseOfImage; //Ok, now we have the base address of the exectable file in memory (remember before, when i said that i'll show you how to get it?)
      }

      if(dEvent.dwDebugEventCode==EXIT_PROCESS_DEBUG_EVENT) //if process terminated, then break the loop, so that you would exit function
          break;

      if(dEvent.dwDebugEventCode==EXCEPTION_DEBUG_EVENT)//Check for breakpoint
      {
          if(dEvent.u.Exception.ExceptionRecord.ExceptionCode==EXCEPTION_BREAKPOINT)
          {//It is a break point;
             if(BREAK1==FALSE)
             {//First Breakpoint occured
                B = InjectDLL( pInfo.hProcess, pInfo.hThread, BaseOfImage,  
                    DLLTOINJECT); //The magical function, comes after this function

                BREAK1 = TRUE;
                if(!B)
                    return FALSE;
             }else if(BREAK2==FALSE)
             {//Second breakpoint occured (asm instructions have been all done, and int 3h was reached
                ret = RestoreOriginalCodePage( PHandle, THandle, 0); //another function to restore
                if(ret==0) return FALSE; //uhoh!!! Big big big big error...you need to restore what you have written, but couldn't,,,,i'll leave it to you, cause i, my self donno what to do, other than terminate the target process :P
                BREAK2=TRUE;
             }
          }else
          {    //if an Exception occured, and it wasn't a break point, then say DBG_EXCEPTION_NOT_HANDLED
             //Because you haven't handled the exception, so let lindows,,i mean, windows handle it..
             ContinueDebugEvent( dEvent.dwProcessId, dEvent.dwThreadId, DBG_EXCEPTION_NOT_HANDLED);
             continue;
          }

      }//end if

      ContinueDebugEvent( dEvent.dwProcessId, dEvent.dwThreadId, DBG_CONTINUE);
      //you don't need to handle event,,let it pass

   }//end while()
}//end function



next function:

BOOL InjectDLL(HANDLE hProcess, HANDLE hThread, VOID* hModuleBase, char *DllName)
{//You must have debug access to hProcess (required for ReadProcessMemory() & WriteProcessMemory)

   FARPROC LoadLibProc = GetProcAddress(GetModuleHandle("KERNEL32.dll"), "LoadLibraryA");
   if(!LoadLibProc) return FALSE;

//This is the entry point addr of LoadLibrary()...It's usually, always the same for any process that loads kernel32.dll
//So unless there is some other explanation, i don't know
//But i personally found that this works all of the time
   

   
   
   char CodePage[4096] =
   
   {    0xB8, 00, 00, 00, 00,    // mov EAX,  0h | Pointer to LoadLibraryA() (DWORD)
      0xBB, 00, 00, 00, 00,    // mov EBX,  0h | DLLName to inject (DWORD)
      0x53,                 // push EBX
      0xFF, 0xD0,              // call EAX
      0x5b,                 // pop EBX
      0xcc                 // INT 3h
   }; //i could have used structS instead, but unfortunatelly, because of many compilers' stupid padding, i didn't >:(
   int nob=15; //no of bytes
   
      char *DLLName;     //DllName
      DWORD *EAX, *EBX;   //Look at codepage

      DLLName = (char*)((DWORD)CodePage + nob);  //Set the pointers
      EAX = (DWORD*)( CodePage +  1);          //
      EBX = (DWORD*) ( CodePage +  6);      //

      strcpy( DLLName, DllName );       //copy dll name
      *EAX = (DWORD)LoadLibProc;       //EAX==LoadLibProc
      *EBX = nob; // need to do this: *EBX = *EBX + (offset of CodePage)
   
      sizeofCP = strlen(DllName) + nob +1; //remember this? --


//Here comes the complicated part, you can use CreateRemoteThread() instead of all this, actually, but unfortunatelly
//it isn't supported in all versions of windows...but i'll tell you how to use it after this code..
//I have an example code that i found from google groups

   IMAGE_DOS_HEADER       DOShdr;
   IMAGE_NT_HEADERS       *pNThdr, NThdr;
   IMAGE_SECTION_HEADER       SecHdr, *pSecHdr;
   IMAGE_DATA_DIRECTORY       DataDir, *pDataDir; //@@@@@@@@
   DWORD              dwD, dwD2, read, written;
   CONTEXT              Context; //GetThreadContext's parameter &&
   BOOL              B;

   Context.ContextFlags = CONTEXT_CONTROL; //look at WINNT.h header file for more information
   OriginalContext.ContextFlags = CONTEXT_CONTROL;
   if(!GetThreadContext( hThread, &OriginalContext)) //Save original context -- remember that currently the process is totally suspended
   {
      dwD = GetLastError();
      return FALSE;
   }
      
   // Check to see if we have valid Headers:
   //
   /Get DOS hdr
   B = ReadProcessMemory(hProcess, hModuleBase, &DOShdr, sizeof(DOShdr), &read);
   if( (!B) || (read!=sizeof(DOShdr)) ) return FALSE;
   if( DOShdr.e_magic != IMAGE_DOS_SIGNATURE ) //Check for `MZ
      return FALSE;
   
   //Get NT header
   B = ReadProcessMemory( hProcess,
      (VOID*)((DWORD)hModuleBase + (DWORD)DOShdr.e_lfanew), &NThdr, sizeof(NThdr), &read);
   if( (!B) || (read!=sizeof(NThdr)) ) return FALSE;
   if( NThdr.Signature != IMAGE_NT_SIGNATURE ) //Check for `PE/0/0
      return 0;

   // Valid EXE header!
   // Look for a usable writable code page: -- this is where you seek the sections for a usable section
   //

   /
      //
      if( (dwD=NThdr.FileHeader.NumberOfSections) < 1 ) //Number of sections must be atleast 1...DUH!!!
          return FALSE;//Section table: (after optional header)
      
      pSecHdr = (IMAGE_SECTION_HEADER*)
          (
          ((DWORD)hModuleBase + (DWORD)DOShdr.e_lfanew) +
          (DWORD)sizeof(NThdr.FileHeader) +
          (DWORD)NThdr.FileHeader.SizeOfOptionalHeader + 4
          );//@@@@@@@@@@@@@ need to concentrate on this to understand..except the +4,,,i saw that it always needs this,, i spent an hour trying to fix an error, until i noticed this :P...So just do it

      B=FALSE;
///GetModuleHandle(0); //i explained what this does, in part I,,,but unfortunatelly, it&#39;s for the dll, not for this exe :P
      
      for( dwD2=0 ; dwD2<dwD ; dwD2++ )
      {//iterate sections to look for a writable part of memory and NOT .idata -- because .idata is the import table,,which shouldn&#39;t be modified whatsoever -- because NazSoft sez so! :P it&#39;s a bit of a long story,,I&#39;m not a super novel to give you all the information u need :P
          if( !ReadProcessMemory( hProcess, pSecHdr, &SecHdr, sizeof(SecHdr), &read) )
             return FALSE; //i know you might look confused of what you see here...

///But listen to me when i say that this is not wrong. it is correct
///pSecHdr points to addr in memory of a section&#39;s name,,but not the memory of MY process,
///but the memory of the other process. If you do *pSecHdr,, you&#39;ll get info from you&#39;re process
///mostly, it&#39;ll be the same as the other proceess, but if you look closer, you&#39;ll see that it&#39;s not
///Base addresses of all dll file&#39;s functions are the same in all programs
///So pSecHdr isn&#39;t a true pointer,, just an easier way (so that i don&#39;t need to use casting opers alot)
///to do what i want to do


          if(read!=sizeof(SecHdr)) return FALSE; //Make sure correct amount was read in
         
          if(
             (SecHdr.Characteristics & IMAGE_SCN_MEM_WRITE) //writable section
             &&
             ( strcmpi((const char*)SecHdr.Name, ".idata")!=NULL ) //not .idata (import data)
             ) //strcmpi -- the "i" == ignore cases (capital, small letters...)
          {
             B = TRUE;
             break;//OK! found!!
          }
          pSecHdr++;
      }

      if(!B)
          return FALSE; //couldn&#39;t find usable code page!
      //
   /
      //Found a section:  (SecHdr.VirtualAddress + (DWORD)hModuleBase)
      mySec = (VOID*)(SecHdr.VirtualAddress + (DWORD)hModuleBase); //Remember this global var?
      //This is where the asm instructions shuold go

      *EBX = *EBX + (DWORD)mySec; //also remember this??? look at the top of the function
      
      if(!ReadProcessMemory( hProcess, mySec, OriginalCodePage, sizeofCP, &read) )
          return FALSE; //Read the stuff in memory, so that you can restore it
      if(read != sizeofCP)
          return FALSE;

//so now, yuou will have already saved the memory that you&#39;re going to modify, and the thread&#39;s context (registers)
//we&#39;ll restore them later..
      
      //Now starts the mega part! (If an error occurs here, god knows what might happen!
      B = WriteProcessMemory( hProcess, mySec, CodePage, sizeofCP, &written);
      
      if( (written!=0) && (written!=sizeofCP) )  //Uh oh!, System crash might occur now!
      {//****EMERGENCY**** ****EMERGENCY**** ****EMERGENCY**** ****EMERGENCY****
          WriteProcessMemory( hProcess, mySec, OriginalCodePage, sizeofCP, &written);
          // Try to save what you can, and return back to memory
                    
          return FALSE; //might not have worked, so, big s***!
      }

      if((!B) || (written!=sizeofCP))
          return FALSE;
      
      //Ok, injected successfully,
      //You MUST call function RestoreOriginalCodePage() function upon the following breakpoint!
      Context = OriginalContext;
      Context.Eip = (DWORD)mySec; //Change EIP
      B = SetThreadContext(hThread, &Context); //Change EIP
      if(!B) return FALSE; //Lol, it would be funny to get an error here,,,all that goes to waste, and you need to restore what ever it ist hat you chagned :S :S :S

   return 1;
}


//OK go back to InjectDLL_CreateProcess() ... Look at the second break point section:
/*
   ret = RestoreOriginalCodePage( PHandle, THandle, 0); //another function to restore
   if(ret==0) return FALSE;
   //uhoh!!! Big big big big error...you need to restore what you have written, but couldn&#39;t,,,,
   //i&#39;ll leave it to you, cause i, my self donno what to do, other than terminate the target process :P

   BREAK2=TRUE;

*/

OK, so lets have a look at RestoreOriginalCodePage():

*******
Notepad is giving me a headache right now, keeps saying not enough memory.. :P :P
*******

I&#39;m typing the rest in c:/windows/edit.com  program --i love this thing :P



//return values:
//
//    if 0    ->    successful
//    if -1    ->    (0xFFFFFFFF) WriteProcessMemory returned FALSE
//    else    ->    Amount of bytes written + 1
//              (to get exact amount of bytes written, you must decrement return value by one!)
//

DWORD RestoreOriginalCodePage( HANDLE hProcess, HANDLE hThread, DWORD *outSize )
{
   BOOL B;
   DWORD written;
   CONTEXT Context;

   if(outSize) *outSize = sizeofCP; //Just for user&#39;s info

     Context.ContextFlags = CONTEXT_FULL; //look at winnt.h
     GetThreadContext( hThread, &Context); //Get current thread context
          //This isn&#39;t required, it&#39;s just for you to check the return
          //value of LoadLibrary()
          It is in the EAX register (Context.Eax)
     
   B = WriteProcessMemory( hProcess, mySec, OriginalCodePage, sizeofCP, &written );
     //Restore original codepage

     if(!B) return -1;

   if(written!=sizeofCP)
      return written+1;

     //Restore context (EIP)
   B=SetThreadContext( hThread, (CONST CONTEXT*)&OriginalContext);
     if(!B) return -1;

   return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值