Access log for hook api program does not work

c++ / delphi package - dll injection and api hooking
Post Reply
goldenbrown1974
Posts: 7
Joined: Thu Apr 17, 2014 9:57 pm

Access log for hook api program does not work

Post by goldenbrown1974 »

Hello .
i had some change in the DEMO program .
i need to write to log the block application (let assume it is regedit.exe)
but it does not working , it seems that the procedure IGNORE some how

please look :

Code: Select all

function CreateProcessWCallback(appName, cmdLine: pwidechar;
                                processAttr, threadAttr: PSecurityAttributes;
                                inheritHandles: bool; creationFlags: dword;
                                environment: pointer; currentDir: pwidechar;
                                const startupInfo: TStartupInfo;
                                var processInfo: TProcessInformation) : bool; stdcall;


Var
App:string;            // new string to get the application name 
  procedure LogAccess(Run:string);stdcall;
  const
  db='Access.log';
  Var
  MyList: Tstringlist;
  s:string;
  begin
  s:='';
  MyList := Tstringlist.Create;
  try
  if fileexists(db) then mylist.LoadFromFile(db);
  MyList.Add(Run);
   mylist.SaveToFile(db);
   finally
   MyList.Free;
   end

   end;


begin
   
   app:= ExtractFileName(widechartostring(appname)); //convert pwidechar to string 
     
    

   if ExtractFileName(widechartostring(appname))='regedit.exe' then    begin    //if program is regedit.exe then block it
   LogAccess(app)  ; 								// this is the call for the procedure to write regedit.exe 
   ShowMessage('Warning: Not Allowed to run this file');
   SetLastError(ERROR_ACCESS_DENIED);
   result := false;


  end else begin  //all ok , continue
                 result := CreateProcessWNext(appName, cmdLine, processAttr, threadAttr,
                                 inheritHandles, creationFlags,
                                 environment, currentDir,
                                 startupInfo, processInfo);
    RenewHook(@CreateProcessWNext);
  end;
end;

begin
  
   HookAPI('kernel32.dll', 'CreateProcessW', @CreateProcessWCallback, @CreateProcessWNext);

end.
madshi
Site Admin
Posts: 10753
Joined: Sun Mar 21, 2004 5:25 pm

Re: Access log for hook api program does not work

Post by madshi »

"appName" is an optional parameter. Personally, if I create a new process by calling CreateProcessA/W I usually leave "appName" empty. Usually most programs use "cmdLine" when starting new processes. So you might want to look at the "cmdLine". That one might also contain parameters, though, so you can't use "ExtractFileName" for the "cmdLine" parameter.
goldenbrown1974
Posts: 7
Joined: Thu Apr 17, 2014 9:57 pm

Re: Access log for hook api program does not work

Post by goldenbrown1974 »

ok , thanks .

now , after walking into the HELP and this FORUM ,i wish to transfer string to the EXE file

EXE -> HOOK DLL
EXE -> IPC MESSAGE
HOOK DLL -> SEND IPC BACK
EXE ->SHOW IPC DATA

Now , i am under XP with DELPHI 7 .
i tried to stay as close as i can to your code .
I Can transfer string , but not PWIDECHAR . :cry: :cry: :cry: :cry: :cry: :cry: :cry:
can you help ?
this is the code

The DLL:
***********
please look for : function CreateProcessWCallback

Code: Select all

// ***************************************************************
//  HookProcessCreation.dll   version:  1.0   ·  date: 2003-06-15
//  -------------------------------------------------------------
//  hook all process creation calls and ask for confirmation
//  -------------------------------------------------------------
//  Copyright (C) 1999 - 2003 http://www.madshi.net, All Rights Reserved
// ***************************************************************

// 2003-06-15 1.0  initial release

library SM1;

{$IMAGEBASE $57800000}

uses  Windows, madCodeHook,PsAPI,   Classes,sysutils,dialogs
 ,    madRemote, madStrings;



    type
    TTerminationRequest = record
    system             : boolean;
    process1, process2 : array [0..MAX_PATH] of char;
    p:pwidechar;
    end;



  // this is the information we send to our application
 var tr      : TTerminationRequest;
      session : dword;


            // session : dword;
    //question,answer:string;



function IsAllowed(appNameA, cmdLineA: pchar; appNameW, cmdLineW: PWideChar) : boolean;
// ask the user whether the current process may execute the specified command line
var arrChA   : array [0..MAX_PATH * 3] of char;
    arrChW   : array [0..500] of wideChar;
    pc       : pchar;
    question : array [0..500] of char;
    i1, i2   : integer;
begin



 // showMessage(AppNamea);
  if not AmSystemProcess then begin
    // ask the name of the current process
    if GetVersion and $80000000 = 0 then begin
      GetModuleFileNameW(0, arrChW, MAX_PATH);
      WideToAnsi(arrChW, arrChA);
    end else
      GetModuleFileNameA(0, arrChA, MAX_PATH);
    // we only want the file name
    i2 := 0;
    for i1 := lstrlenA(arrChA) - 1 downto 0 do
      if arrChA[i1] = '\' then begin
        i2 := i1 + 1;
        break;
      end;

    lstrcpyA(question, 'May the process ');
    lstrcatA(question, @arrChA[i2]);
    lstrcatA(question, ' execute the following line?' + #$D#$A + #$D#$A);
    // let's get a command line string which we can show to the user
    try
      if cmdLineA <> nil then begin
        pc := pointer(LocalAlloc(LPTR, lstrlenA(cmdLineA) + 1));
        lstrcpyA(pc, cmdLineA);
      end else
        if cmdLineW <> nil then begin
          pc := pointer(LocalAlloc(LPTR, lstrlenW(cmdLineW) + 1));
          WideToAnsi(cmdLineW, pc)
        end else
          if appNameA <> nil then begin
            pc := pointer(LocalAlloc(LPTR, lstrlenA(appNameA) + 1));
            lstrcpyA(pc, appNameA);
          end else begin
            pc := pointer(LocalAlloc(LPTR, lstrlenW(appNameW) + 1));
            WideToAnsi(appNameW, pc);
          end;
      if lstrlenA(pc) > MAX_PATH then
        pc[MAX_PATH] := #0;
      lstrcatA(question, pc);
      LocalFree(dword(pc));
    except
      lstrcatA(question, '??? (invalid command line!)');
    end;
    // finally let's ask the user
    if GetVersion and $80000000 = 0 then begin
      AnsiToWide(question, arrChW);
      //ShowMessage(pc);
      //ShowMessage(WideCharToString(arrchw)+','+Md5Hash(WideCharToString(Arrchw)));
      //  question[2]:='@';
       // AnsiToWide(question, arrChW);   showMessage(question);

      result := MessageBoxW(0, arrChW, 'Question', MB_ICONQUESTION or MB_YESNO or MB_TASKMODAL or MB_TOPMOST) = ID_YES;
    end else
      result := MessageBoxA(0, question, 'Question', MB_ICONQUESTION or MB_YESNO or MB_TASKMODAL or MB_TOPMOST) = ID_YES;
  end else
    // let's allow system processes to execute whatever they want
    result := true;
end;
        
// ***************************************************************

var
  CreateProcessANext  : function (appName, cmdLine: pchar;
                                  processAttr, threadAttr: PSecurityAttributes;
                                  inheritHandles: bool; creationFlags: dword;
                                  environment: pointer; currentDir: pchar;
                                  const startupInfo: TStartupInfo;
                                  var processInfo: TProcessInformation) : bool; stdcall;
  CreateProcessWNext  : function (appName, cmdLine: pwidechar;
                                  processAttr, threadAttr: PSecurityAttributes;
                                  inheritHandles: bool; creationFlags: dword;
                                  environment: pointer; currentDir: pwidechar;
                                  const startupInfo: TStartupInfo;
                                  var processInfo: TProcessInformation) : bool; stdcall;
  WinExecNext         : function (cmdLine: pchar; show: dword) : dword; stdcall;

function CreateProcessACallback(appName, cmdLine: pchar;
                                processAttr, threadAttr: PSecurityAttributes;
                                inheritHandles: bool; creationFlags: dword;
                                environment: pointer; currentDir: pchar;
                                const startupInfo: TStartupInfo;
                                var processInfo: TProcessInformation) : bool; stdcall;
begin
  if not IsAllowed(appName, cmdLine, nil, nil) then begin
    // the user doesn't like this CreateProcess call, so we block it
    result := false;
    SetLastError(ERROR_ACCESS_DENIED);
  end else begin
    // this CreateProcess call is okay
    result := CreateProcessANext(appName, cmdLine, processAttr, threadAttr,
                                 inheritHandles, creationFlags,
                                 environment, currentDir,
                                 startupInfo, processInfo);
    // CreateProcess hooks are used very often, so to be sure we renew the hook
    RenewHook(@CreateProcessANext);
  end;
end;

function CreateProcessWCallback(appName, cmdLine: pwidechar;
                                processAttr, threadAttr: PSecurityAttributes;
                                inheritHandles: bool; creationFlags: dword;
                                environment: pointer; currentDir: pwidechar;
                                const startupInfo: TStartupInfo;
                                var processInfo: TProcessInformation) : bool; stdcall;

Var
r :boolean;
s:string;
begin
    tr.system := AmSystemProcess;
    tr.process1:='123';
    tr.process2:='456';
    s:=WideCharToString(appname);
    tr.p:=cmdLine;
                                         //tr.p:= Pchar(s)+'#0'  ;
                                       //  tr.p:='122234'+#0 ;    //V
                                         //tr.p:=appname+#0 ;   //V



                                        //TR.My:=WIDECHARTOSTRING(Appname);

                                     //   s:=WIDECHARTOSTRING(Appname);
                                      //  s1:=Pchar(s1);
                                      //  tr.process1:=s1;
                                           // showMessage('I will send:'+tr.p);
    //ProcessIdToFileName(GetCurrentProcess, tr.process1);
    //ProcessIdToFileName(GetCurrentProcess, tr.process2);
//AskApplication('abc');
  if  SendIpcMessage(pchar('HookProcessTermination' + IntToStrEx(session)),
                          @tr,     sizeOf(tr),            // our message
                          @result, sizeOf(result))   // the answer


     =true then // ShowMessage('Send ok');
  //ShowMessage(Result)
  if not IsAllowed(nil, nil, appName, cmdLine) then begin
    result := false;
   // SetLastError(ERROR_ACCESS_DENIED);

  end else begin
    result := CreateProcessWNext(appName, cmdLine, processAttr, threadAttr,
                                 inheritHandles, creationFlags,
                                 environment, currentDir,
                                 startupInfo, processInfo);
    //ScanApp:=AppName;
    RenewHook(@CreateProcessWNext);
  end;
end;

function WinExecCallback(cmdLine: pchar; show: dword) : dword; stdcall;
begin
  if not IsAllowed(nil, cmdLine, nil, nil) then
    result := ERROR_ACCESS_DENIED
  else begin
    result := WinExecNext(cmdLine, show);
    RenewHook(@WinExecNext);
  end;
end;

// ***************************************************************



begin


   HookAPI('kernel32.dll', 'CreateProcessA', @CreateProcessACallback, @CreateProcessANext);
  HookAPI('kernel32.dll', 'CreateProcessW', @CreateProcessWCallback, @CreateProcessWNext);
  HookAPI('kernel32.dll', 'WinExec',        @WinExecCallback,        @WinExecNext       );
   




end.
the EXE main project : Form1 , 2 memo , 1 as log , 1 as memo1
please look for : procedure HandleProcessTerminationRequest

Code: Select all

unit Unit1;

interface

uses
   Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls  ,
    madCodeHook, madStrings, CommDlg;

Const
//dllFileW='HookProcessCreation.dll';
dllFileW='sm1.dll';

type
  TForm1 = class(TForm)
    CheckBox1: TCheckBox;
    Log: TMemo;
    Memo1: TMemo;
    procedure CheckBox1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  private
    { Private declarations }
    Procedure  DoHook;
    Procedure  DoUnHook;


  public
    { Public declarations }
  end;

type

  // this is the information record which our dll sends us
    TTerminationRequest = record
    system             : boolean;
    process1, process2 : array [0..MAX_PATH] of char;
    p:pwidechar;

  end;
  // this is the information we send to our application

    Var
    T:TTerminationRequest;

   // session : dword;
    //question,answer:string;


var
  Form1: TForm1;
   b1,running : boolean;
implementation

{$R *.dfm}


// {$R mad.res}
 //{$R needAdminRights.res}


procedure HandleProcessTerminationRequest(name       : pchar;
                                          messageBuf : pointer;
                                          messageLen : dword;
                                          answerBuf  : pointer;
                                          answerLen  : dword);  stdcall;
// this function is called by the ipc message whenever our dll contacts us
var s1, s2, s3 : string;
begin
  //try
  if AmUsingInputDesktop then begin
    // our process is running in the current input desktop, so we ask the user
    with TTerminationRequest(messageBuf^) do begin
      // first extract the file names only
    //  s1 := ExtractFileName(process1);
     // s2 := ExtractFileName(process2);
      Form1.Memo1.lines.add(Process1);
      Form1.Memo1.lines.add(Process2);

      s1:=widechartostring(p);    /problem ????
      Form1.Memo1.lines.add(s1);

            end;
      // does the request come from a normal process or from a system process?
    {  if system then
           s3 := 'system process '
      else s3 := 'process ';
      s3 := 'May the ' + s3 + s1 + ' terminate the following process?' + #$D#$A + #$D#$A + s2;
    end;
    // ask the user for confirmation and return the answer to our dll
    boolean(answerBuf^) := MessageBox(0, pchar(s3), 'Question...',
                                      MB_ICONQUESTION or MB_YESNO or MB_TOPMOST) = ID_YES;
  end else
    // our process is *not* running in the current input desktop
    // if we would call MessageBox, it would not be visible to the user
    // so doing that makes no sense, it could even freeze up the whole OS
    boolean(answerBuf^) := true;  }
end;

//except      on E: Exception do ShowMessage(E.Message+' . '+E.ClassName);   END

      end;






//dllFileW:PWideChar;

{    dllFileA : array [0..MAX_PATH] of char;      // 9x
    dllFileW : array [0..MAX_PATH] of wideChar;  // nt
 }
 


Procedure Tform1.DoHook;
begin
       Log.Lines.Add('Try To Hook...');
     //  dllFileW:='HookProcessCreation.dll';
       b1 := InjectLibraryW(CURRENT_USER, dllFileW);
       if b1=true then   begin
                         Log.Lines.Add('Hook Completed...');running:=true;
                       //  timer1.Enabled:=running;

      if CreateIpcQueue(pchar('HookProcessTermination' + IntToStr(GetCurrentSessionId)), HandleProcessTerminationRequest) then begin
                    Log.lines.add('Communication work fine.');
                 //   memo1.Lines.Add(t.process1;  )
                    End;

                         end
         else  Log.Lines.Add('Only users with administrator privileges can do this');
          
end;



Procedure Tform1.DoUnHook;
begin
Application.ProcessMessages;
       Log.Lines.Add('Try To UnHook...');
        // dllFileW:='HookProcessCreation.dll';
         if DestroyIpcQueue(pchar('HookProcessTermination' + IntToStr(GetCurrentSessionId))) then begin
                    Log.Lines.add('Communication Ended .');
                   //  Application.ProcessMessages;
                        End;
         b1 := UnInjectLibraryW(CURRENT_USER, dllFileW);
         if b1=true then  begin
                          Log.Lines.Add('UnHook Completed...');
                          running:=false;
                    //      timer1.Enabled:=running;

                         // Application.ProcessMessages;
                          end
         else  Log.Lines.Add('Only users with administrator privileges can do this');

         //Application.ProcessMessages;
end;


procedure TForm1.CheckBox1Click(Sender: TObject);

begin

Case CheckBox1.Checked of

true : begin
       
       DoHook;
       end; // of true

false : begin
        DoUnHook;
        end;  // pf false

end; // of case
        //InitDllFile;



end;

procedure TForm1.FormCreate(Sender: TObject);
begin
//dllFileW:='sm1.dll';
running :=false;
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
//action:=caNone;
form1.Cursor:=crHourGlass;      Application.ProcessMessages   ;

Log.Lines.Add('bye bye.');
if running=true then  begin DoUnHook;  Application.ProcessMessages   ;Application.ProcessMessages   ;end;

Application.ProcessMessages   ;
Sleep(4000);
        

end;

end.
Attachments
Err1.jpg
Err1.jpg (140.63 KiB) Viewed 6076 times
Err.jpg
Err.jpg (61.31 KiB) Viewed 6076 times
madshi
Site Admin
Posts: 10753
Joined: Sun Mar 21, 2004 5:25 pm

Re: Access log for hook api program does not work

Post by madshi »

First of all you don't have to use complicated conversion routines. Just use simple type conversion, e.g. instead of "s1:=widechartostring(p)" you can simply do "s1:=string(WideString(p));". However, this is not the cause of the problem, using "widechartostring" probably works just fine. The key problem is that you're trying to transport a PWideChar pointer from the hooked process to your own application. This *cannot* work because we're talking about 2 different processes here, and a pointer is only valid in its own process. The "cmdLine" pointer is only valid in the hooked process. You can't transport the pointer to your own application and expect the pointer to point to the same string. Windows has a totally separate memory area for every process. You will have to copy the actual string data to the TTerminationRequest record. You can see how the original demo does it.
goldenbrown1974
Posts: 7
Joined: Thu Apr 17, 2014 9:57 pm

Re: Access log for hook api program does not work

Post by goldenbrown1974 »

i did not figure how it does (in your program)
can you fix it for me ?
madshi
Site Admin
Posts: 10753
Joined: Sun Mar 21, 2004 5:25 pm

Re: Access log for hook api program does not work

Post by madshi »

Hey, I can't do all the work for you. These are very basic programming things. And you even have a demo which does everything correctly.
Post Reply