Page 1 of 1

[Solved]Simple DLL inject problem

Posted: Wed Jul 03, 2024 5:40 pm
by le_magn
Hi all, I would like to inject a dll, which once inside calls an internal function of the process, so far I have succeeded, the dll is injected(with esternal iniector), the command is executed ok, but after the command is executed the process interface disappears and remains active in the background, any suggestions? p.s. If i remove freememory(*testo) it work ok...
Main process:

Code: Select all

CompilerIf #PB_Compiler_IsMainFile
  EnableExplicit
CompilerEndIf

;- Enumerations
Enumeration Window
  #Window_0
EndEnumeration

Enumeration Gadgets
  #Btn_1
  #Edit_1
EndEnumeration

Global Quit

;- Declare
Declare Open_Window_0(X = 0, Y = 0, Width = 320, Height = 180)

Procedure Mia_AddGadgetItem(gadget, Posizione, Stringa.s, acapo = 1)
  AddGadgetItem(gadget, posizione, Stringa)
  SendMessage_(GadgetID(gadget), #EM_SETSEL, $fffffff, $fffffff)
EndProcedure

Procedure Mia_TESTO(TESTO.S)
  Mia_AddGadgetItem(#Edit_1, - 1, TESTO, 1)
EndProcedure

Procedure Open_Window_0(X = 0, Y = 0, Width = 320, Height = 180)
  If OpenWindow(#Window_0, X, Y, Width, Height, "Title", #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_TitleBar | #PB_Window_ScreenCentered)
    ButtonGadget(#Btn_1, 100, 20, 100, 24, "Button_1")
    EditorGadget(#Edit_1, 0, 60, 320, 120)
    ProcedureReturn #True
  EndIf
EndProcedure

CompilerIf #PB_Compiler_IsMainFile
;- Main Program
  If Open_Window_0()
    
  ;- Event Loop
    Repeat
      Select WaitWindowEvent()
        Case #PB_Event_CloseWindow
          Quit = #True
          
        ;-> Event Gadget
        Case #PB_Event_Gadget
          Select EventGadget()
            Case #Btn_1
              Mia_TESTO("TESTO ORIGINALE")
          EndSelect
          
      EndSelect
    Until Quit
  EndIf
CompilerEndIf
DLL:

Code: Select all

ProcedureDLL AttachProcess(Instance)

  ;   MessageRequester("AttachProcess()", Str(GetModuleHandle_("test.exe")))
  Delay(1000)
  testo.s = "testo modificato"
  lun.l = Len(testo)
  *TESTo = AllocateMemory(lun)
  PokeS(*testo, testo, lun)
  *funzione = GetModuleHandle_("test.exe") + $11B2
  ;   CallCFunctionFast(*FUNZIONE, *testo)
  CallFunctionFast(*FUNZIONE, *testo)
  FreeMemory(*testo)
EndProcedure

ProcedureDLL DetachProcess(Instance)
; printN("2")
  
EndProcedure

ProcedureDLL AttachThread(Instance)
; printN("3")
EndProcedure

ProcedureDLL DetachThread(Instance)
; printN("4")
  
EndProcedure
P.S. i want to do this because i want to create dll to inject in a game, for translate the internal strings in other language...

Re: Simple DLL inject problem

Posted: Wed Jul 03, 2024 7:00 pm
by Caronte3D
le_magn wrote: Wed Jul 03, 2024 5:40 pm ...but after the command is executed the process interface disappears and remains active in the background, any suggestions?
Maybe do *testo Global and change FreeMemory(*testo) to DetachProcess(Instance)?

Re: Simple DLL inject problem

Posted: Wed Jul 03, 2024 7:38 pm
by le_magn
Caronte3D wrote: Wed Jul 03, 2024 7:00 pm Maybe do *testo Global and change FreeMemory(*testo) to DetachProcess(Instance)?
Yes it work!!! thank you

Re: Simple DLL inject problem

Posted: Thu Jul 04, 2024 12:50 pm
by le_magn
Now a nice big problem has arisen, basically in a 32bit process I can change the call of the original process by putting the address pointing to the call in my dll, for 64bit processes it is not so simple, if I use a small executable to do the test all ok, but using for example the executable of the game I am interested in translating, the address of the function in the dll turns out to be too far away from the main process(it need more than 4 bytes) , in these cases how could be solved? thanks

Re: Simple DLL inject problem

Posted: Thu Jul 04, 2024 6:16 pm
by Caronte3D
PB integers size are 8 bytes if you use a 64 bits compiler

Re: Simple DLL inject problem

Posted: Thu Jul 04, 2024 6:56 pm
by le_magn
yes but original function use 5 bytes for call , jmp+address, if i want to call my procedure in dll i need to use more than 8 bytes, if i overwrite the original code i write also to next instructions and program crash, only way i think is to use a intermediate jump to code cave in original process, and write here some instruction to call my procedure... is a bit complicate compared with normal 32bit.

UPDATE: i solved the problem above, but now i have other issue, if i call my procedure and i use original buffer(buffer contain original text passed to my procedure) it work, but if i want to resize this buffer or allocate new buffer i receive error, invalid memory access or other, try allocatememory() and reallocatememory() same problem, any suggestion is appreciated thank you......

Re: Simple DLL inject problem

Posted: Tue Jul 09, 2024 9:58 am
by Smitis
Could there be a mistake in this:
len(testo) - length in symbols
AllocateMemory(lun) - length in bytes
Plus need two more bytes for terminate zero symbol.

It's better to do this:
*testo = AllocateMemory(StringByteLength(testo)+SizeOf(Character))

Re: Simple DLL inject problem

Posted: Tue Jul 09, 2024 11:23 am
by le_magn
Smitis wrote: Tue Jul 09, 2024 9:58 am Could there be a mistake in this:
len(testo) - length in symbols
AllocateMemory(lun) - length in bytes
Plus need two more bytes for terminate zero symbol.

It's better to do this:
*testo = AllocateMemory(StringByteLength(testo)+SizeOf(Character))
Yes you are right, string need to terminate with 00 byte, and lenght need to be calculated in byte, sometimes we make trivial mistakes, thank you

Re: Simple DLL inject problem

Posted: Sun Jul 14, 2024 1:02 am
by le_magn
I have made progress, I am able to divert the original process function to a memory area where I have set up a trampoline(necessary for 64bit) to call my function in the dll, my function is called and 3 parameters are passed, from my function I am able to read these parameters, and so far so good, but here the headaches start, out of these 3 parameters I am interested in the 2nd and 3rd parameters, which are text and text size respectively, I read them with printn(peeks(*buffer,-1,#pbutf8)) but if I try to pass the text in a variable string string.s=peeks(*buffer,-1,#pbutf8)), it crashes, if instead I use a fixed string for example *fixedbuffer=utf8("example string") the program does not crash...

this not crash:

Code: Select all

ProcedureCDLL My_Function(*primo, *secondo, ProgramParam3);, IGNORARE IL PRIMO
  Protected *funzione, Speciale, *Tradotto,Stringa.s,*test
  *funzione = GetModuleHandle_("myprocess.exe") + $D111
PrintN("STRINGA_READMEMORY: "+PeekS(*SECONDO,-1,#PB_UTF8))<--------------------------
CallCFunctionFast(*funzione + 5, *primo, *ProgramParam2, ProgramParam3); Terzo
 ProcedureReturn
EndProcedure
this not crash:

Code: Select all

ProcedureCDLL My_Function(*primo, *ProgramParam2, ProgramParam3);, IGNORARE IL PRIMO
  Protected *funzione, Speciale, *Tradotto,Stringa.s
  *funzione = GetModuleHandle_("myprocess.exe") + $D111
PrintN("STRINGA_READMEMORY: "+PeekS(*SECONDO,-1,#PB_UTF8))
*test=utf8("example string")<---------------------------
CallCFunctionFast(*funzione + 5, *primo, *Secondo, ProgramParam3); + StringByteLength(Testo2)
 ProcedureReturn
EndProcedure
this crash:

Code: Select all

ProcedureCDLL My_Function(*primo, *secondo, ProgramParam3);, IGNORARE IL PRIMO
  Protected *funzione, Speciale, *Tradotto,Stringa.s
  *funzione = GetModuleHandle_("myprocess.exe") + $D111
STRINGA=PeekS(*ProgramParam2,-1,#PB_UTF8) <-----------------------
CallCFunctionFast(*funzione + 5, *primo, *Secondo, ProgramParam3); + StringByteLength(Testo2)
 ProcedureReturn
EndProcedure
this also crash:

Code: Select all

ProcedureCDLL My_Function(*primo, *secondo, ProgramParam3);, IGNORARE IL PRIMO
  Protected *funzione, Speciale, *Tradotto,Stringa.s
  *funzione = GetModuleHandle_("myprocess.exe") + $D111
STRINGA=""<-----------------------
CallCFunctionFast(*funzione + 5, *primo, *Secondo, ProgramParam3); + StringByteLength(Testo2)
 ProcedureReturn
EndProcedure
also crash with MemorySize(*secondo), and crash sometime also with only peeks, how to check if buffer is accessible and readable to avoid problem?