PureInjector 32 Bits

Share your advanced PureBasic knowledge/code with the community.
xorc1zt
Enthusiast
Enthusiast
Posts: 276
Joined: Sat Jul 09, 2011 7:57 am

PureInjector 32 Bits

Post by xorc1zt »

A dll injector with a GUI.

Code: Select all

; PureInjector x86
; xorc1zt
; 2011

#VERSION = "1.0"

Enumeration
  #INJECTION
  #UNLOAD
EndEnumeration

Structure ProcessListStr
  ProcessName.s
  ProcessID.l
EndStructure

Structure ModuleListStr
  ModuleName.s
  ModuleAddress.l
  ModulePath.s
EndStructure

Global NewList ProcessList.ProcessListStr()
Global NewList ModuleList.ModuleListStr()
Global SelectedProcess.l
Global SelectedModule.s
Global ConsoleBuff.s
Global DLLToInject.s

; Refresh the console buff and go to the last line
Procedure UpdateConsole()
  SetGadgetText(2, ConsoleBuff)
  lines=SendMessage_(GadgetID(2),#EM_GETLINECOUNT,0,0)
    SendMessage_(GadgetID(2), #EM_LINESCROLL, 0, lines)
EndProcedure

; Parse each procress name and each process id to the linked list ProcessList()
Procedure.b GetProcesslist()
  ;clear process list and gadget
  ClearList(ProcessList()) 
  ClearGadgetItems(0)
  
  hProcessSnap.i = CreateToolhelp32Snapshot_(#TH32CS_SNAPPROCESS, NULL)
  If( hProcessSnap = #INVALID_HANDLE_VALUE ) : ProcedureReturn #False : EndIf
  
  ;initialize process structure
  ProcessInfos.PROCESSENTRY32
  ProcessInfos\dwSize = SizeOf(PROCESSENTRY32)
  
  ;parse first process on the list
  Process32First_(hProcessSnap, @ProcessInfos)
  AddElement(ProcessList())
  ProcessList()\ProcessName = PeekS(@ProcessInfos\szExeFile)
  ProcessList()\ProcessID = ProcessInfos\th32ProcessID
  AddGadgetItem(0, -1, Str(ProcessList()\ProcessID)+Chr(10)+ProcessList()\ProcessName)
  ;parse next process on the list
  While Process32Next_(hProcessSnap, @ProcessInfos) > 0
    AddElement(ProcessList())
    ProcessList()\ProcessName = PeekS(@ProcessInfos\szExeFile)
    ProcessList()\ProcessID = ProcessInfos\th32ProcessID
    AddGadgetItem(0, -1, Str(ProcessList()\ProcessID)+Chr(10)+ProcessList()\ProcessName)
  Wend
  ConsoleBuff+Str(ListSize(ProcessList()))+" Processus found"+#CRLF$
  UpdateConsole()
  ProcedureReturn #True
EndProcedure

; Parse each module from process id to the linked list ModuleList()
Procedure.b GetModuleList(ProcessID.l)
  ;clear module list and gadget
  ClearList(ModuleList()) 
  ClearGadgetItems(1)
  
  hProcessSnap.i = CreateToolhelp32Snapshot_(#TH32CS_SNAPMODULE, ProcessID)
  
  If( hProcessSnap = #INVALID_HANDLE_VALUE ) 
    ErrorCode.l = GetLastError_()
    Select ErrorCode
      Case 5 ; acces denied
        ConsoleBuff+ProcessList()\ProcessName+": Access denied"+#CRLF$
      Case 299 ; 32 bits processus can't read 64 bits processus
        ConsoleBuff+ProcessList()\ProcessName+" is a 64 bits processus"+#CRLF$
    EndSelect
    UpdateConsole()
    ProcedureReturn #False
  EndIf
  
  ModuleInfos.MODULEENTRY32
  ModuleInfos\dwSize = SizeOf(MODULEENTRY32)
  Module32First_(hProcessSnap, @ModuleInfos)
; first module is alway the target process 
;   AddElement(ModuleList())
;   ModuleList()\ModuleName = PeekS(@ModuleInfos\szModule)
;   ModuleList()\ModuleAddress = ModuleInfos\modBaseAddr
;   ModuleList()\ModulePath = PeekS(@ModuleInfos\szExePath)
;   AddGadgetItem(1, -1, Str(ModuleList()\ModuleAddress)+Chr(10)+ModuleList()\ModuleName)

  While Module32Next_(hProcessSnap, @ModuleInfos) > 0
    AddElement(ModuleList())
    ModuleList()\ModuleName = PeekS(@ModuleInfos\szModule)
    ModuleList()\ModuleAddress = ModuleInfos\modBaseAddr
    ModuleList()\ModulePath = PeekS(@ModuleInfos\szExePath)
    AddGadgetItem(1, -1, Hex(ModuleList()\ModuleAddress)+Chr(10)+ModuleList()\ModuleName)
  Wend
  ConsoleBuff+ProcessList()\ProcessName+": "+Str(ListSize(ModuleList()))+" Modules found"+#CRLF$
  UpdateConsole()
EndProcedure

Procedure.b DLL(dwProcessId.l, pszLibFile$, Mode.b = 0)
  hProcess.i
  hThread.i
  lzLibFileRemote.i
  lSize.i
  endSize.i
  lsThreadRtn.i
  hProcess = OpenProcess_(#PROCESS_QUERY_INFORMATION | #PROCESS_CREATE_THREAD | #PROCESS_VM_OPERATION | #PROCESS_VM_WRITE, 0, dwProcessId)
  If hProcess = 0 : Goto ErrHandle : EndIf
  lSize = 1 + Len(pszLibFile$)
  endSize = lSize

  OpenLibrary(0, "Kernel32.dll")
  If mode
    modestr.s = "Unload"
    lsThreadRtn = GetFunction(0, "GetModuleHandleA")
  Else
    modestr.s = "Injection"
    lsThreadRtn = GetFunction(0, "LoadLibraryA")
    CloseLibrary(0)
  EndIf
  
  lzLibFileRemote = VirtualAllocEx_(hProcess, #Null, endSize, #MEM_COMMIT | #MEM_RESERVE, #PAGE_READWRITE)
  If lzLibFileRemote = 0 : Goto ErrHandle : EndIf
  If Not WriteProcessMemory_(hProcess, lzLibFileRemote, pszLibFile$, endSize, #Null) : Goto ErrHandle : EndIf

  If lsThreadRtn = 0 : Goto ErrHandle : EndIf
  hThread = CreateRemoteThread_(hProcess, #Null, #Null, lsThreadRtn, lzLibFileRemote, #THREAD_QUERY_INFORMATION, #Null)
  If (hThread = 0) : Goto ErrHandle : EndIf
 
  WaitForSingleObject_(hThread, #INFINITE)

  If lzLibFileRemote<>0
    VirtualFreeEx_(hProcess, lzLibFileRemote, 0, #MEM_RELEASE)
  Else
    Goto ErrHandle
  EndIf

  If mode
    hModule.i = 0
    GetExitCodeThread_(hThread, @hModule)
    CloseHandle_(hThread)
    CloseHandle_(hProcess)
    hProcess = OpenProcess_(#PROCESS_QUERY_INFORMATION | #PROCESS_CREATE_THREAD | #PROCESS_VM_OPERATION | #PROCESS_VM_WRITE, 0, dwProcessId)
    lzLibFileRemote = VirtualAllocEx_(hProcess, #Null, 4, #MEM_COMMIT | #MEM_RESERVE, #PAGE_READWRITE)
    If Not WriteProcessMemory_(hProcess, lzLibFileRemote, hModule, 4, #Null) : Goto ErrHandle : EndIf
    lsThreadRtn = GetFunction(0, "FreeLibrary")
    hThread = CreateRemoteThread_(hProcess, #Null, #Null, lsThreadRtn, lzLibFileRemote, #THREAD_QUERY_INFORMATION, #Null)
    WaitForSingleObject_(hThread, #INFINITE)
    GetExitCodeThread_(hThread, @hModule)
    CloseLibrary(0)
    CloseHandle_(hThread)
  EndIf
  
  CloseHandle_(hProcess)
  ConsoleBuff+modestr+" Success"+#CRLF$
  UpdateConsole()
  ProcedureReturn #True
  
  ErrHandle:
      Debug GetLastError_()
      VirtualFreeEx_(hProcess, lzLibFileRemote, 0, #MEM_RELEASE)
      CloseHandle_(hThread)
      CloseHandle_(hProcess)
      ConsoleBuff+modestr+" Failed"+#CRLF$
      UpdateConsole()
      ProcedureReturn #False
EndProcedure
    
#WindowWidth  = 546
#WindowHeight = 565

If OpenWindow(0, 100, 200, #WindowWidth, #WindowHeight, "PureInjector x86 "+#VERSION+" - Xorc1zt", #PB_Window_SystemMenu | #PB_Window_MinimizeGadget)
  
  ;Process list
  ListIconGadget(0, 1, 1, 270, 200, "Process ID", 65, #PB_ListIcon_FullRowSelect)
  AddGadgetColumn(0, 1, "Name", 165)
  
  ;Module list
  ListIconGadget(1, 275, 1, 270, 500, "Base Address", 80, #PB_ListIcon_FullRowSelect)
  AddGadgetColumn(1, 1, "Name", 165)
  
  StringGadget(2, 1, 221, 270, 280, "Hello", #PB_String_ReadOnly | #ES_MULTILINE | #WS_VSCROLL | #WS_HSCROLL)
  ConsoleBuff = "PureInjector ( V"+#VERSION+" "+FormatDate("%dd/%mm/%yyyy - %hh:%ii:%ss", #PB_Compiler_Date)+" )"+#CRLF$
  StringGadget(3, 1, 505, 525, 20, "dll to inject")
  ButtonGadget(4, 525, 505, 21, 20, "...")
  ButtonGadget(5, 0, 525, 545, 20, "Inject !")
  ButtonGadget(6, 0, 545, 545, 20, "Unload selected module")
  ButtonGadget(7, 0, 200, 270, 20, "Refresh list")
  If Not GetProcesslist() : MessageRequester("Error", "GetProcesslist() Failed") : EndIf
  
  Repeat
    EventID = WaitWindowEvent()
    
    If EventID = #PB_Event_Gadget
      Select EventGadget()
        Case 0 ; process list
          If EventType() = #PB_EventType_LeftClick And GetGadgetState(0) > -1
            SelectElement(ProcessList(), GetGadgetState(0))
            SelectedProcess = ProcessList()\ProcessID
            GetModuleList(SelectedProcess)
          EndIf
        Case 1 ; module list
          If EventType() = #PB_EventType_LeftClick And GetGadgetState(1) > -1
            SelectElement(ModuleList(), GetGadgetState(1))
            SelectedModule = ModuleList()\ModulePath;ModuleList()\ModuleName
            ConsoleBuff+ModuleList()\ModuleName+" Path: "+ModuleList()\ModulePath+#CRLF$
            UpdateConsole()
          EndIf
        Case 3 
          If EventType() = #PB_EventType_Change
            DLLToInject = GetGadgetText(3)
          EndIf   
        Case 4
          DLLToInject = OpenFileRequester("Please choose file to load", "", "DLL (*.dll)|*.dll", 0)
          SetGadgetText(3,DLLToInject)
        Case 5 ;inject dll
          DLL(SelectedProcess, DLLToInject)
        Case 6 ;unload unload module
          DLL(SelectedProcess, SelectedModule, #UNLOAD)
        Case 7 ; refresh list
          If Not GetProcesslist() : MessageRequester("Error", "GetProcesslist() Failed") : EndIf
      EndSelect      
    EndIf
       ; 
  Until EventID = #PB_Event_CloseWindow
EndIf
Unload module don't work but dll injection is fine.
Last edited by xorc1zt on Tue Nov 29, 2011 6:42 pm, edited 1 time in total.
SFSxOI
Addict
Addict
Posts: 2970
Joined: Sat Dec 31, 2005 5:24 pm
Location: Where ya would never look.....

Re: PureInjector 32 Bits

Post by SFSxOI »

Nice job....:)

Now do one that streams the .dll to inject from a remote source across the internet, the .dll never touches the hard drive and always remains in memory and nothing is written to the hard drive, then the .dll is injected straight from memory, and oh yeah, the .dll is heavily encrypted and has to be unencrypted bit by bit as it injects and not all at once and it only unencrypts the bits its injecting at the moment, then after injection it vanishes from memory. Thats a tough one :)

(joking about making another by the way :) )


Looks like your getting this thing down pretty well.
The advantage of a 64 bit operating system over a 32 bit operating system comes down to only being twice the headache.
User avatar
Kwai chang caine
Always Here
Always Here
Posts: 5494
Joined: Sun Nov 05, 2006 11:42 pm
Location: Lyon - France

Re: PureInjector 32 Bits

Post by Kwai chang caine »

I have not understand what is the real using of your splendid tools
But for see what is the DLL used by a process, it's super cool :shock:

Thanks a lot for sharing 8)
ImageThe happiness is a road...
Not a destination
Post Reply