__I want to Hide my program__

ok, I want to completely hide my program.. that means..
1· Hide it from the task bar
2· Hide it from ctrl+alt+del
3· Hide it from programs such as Wintop
4· Hide it also when it's ran as a service
5· If it uses TServerSocket, the connection made by my program must not be shown with NETSTAT or any of those commands that show the current internet connections.
menorcanetAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

viktornetCommented:
here... hiding from taskbar...

ShowWindow(Application.Handle, SW_HIDE);

for tht ctrl-del-alt thingy here is the code...

Const RSP_SIMPLE_SERVICE = 1;
Const RSP_UNREGISTER_SERVICE = 0;

//hide
RegisterServiceProcess(GetCurrentProcessId, RSP_SIMPLE_SERVICE);
//show
RegisterServiceProcess(GetCurrentProcessId, RSP_UNREGISTER_SERVICE);

this should be able to hide your application completely.... try it out...

..-=ViKtOr=-..
0
GwenaCommented:
Hmmmm ;-)

So you need a program that nobody can tell is running
And it is running a server on the net.....Hmmmmm
Sounds like a recipe for a back-orifice clone of some sort...
psssssst.....What R U up to anyway?  (I can keep a secret)

;-)


0
intheCommented:
how that gonna stop wintop or netstat?
hungry for 500 points i think :-)
0
Cloud Class® Course: CompTIA Cloud+

The CompTIA Cloud+ Basic training course will teach you about cloud concepts and models, data storage, networking, and network infrastructure.

viktornetCommented:
menorcaret, please REJECT my answer...

i'm otta here....
0
GwenaCommented:
Hmmmm ;-)

So you need a program that nobody can tell is running
And it is running a server on the net.....Hmmmmm
Sounds like a recipe for a back-orifice clone of some sort...
psssssst.....What R U up to anyway?  (I can keep a secret)

;-)


0
intheCommented:
>>menorcaret, please REJECT my answer...
why ?? you deserve some points for answereing 2 of the 5.
i think the other 3 may not be possible anyway.

>>4· Hide it also when it's ran as a service
well WHEN you do this as viktor correctly did:
Const RSP_UNREGISTER_SERVICE = 0;
//hide
RegisterServiceProcess(GetCurrentProcessId, RSP_SIMPLE_SERVICE);
for the reason of hiding a app by telling windows its a service.so the answer to q2 and q4 conflict with each other.

>>how that gonna stop wintop or netstat?
id seriously doubt thats possible i was just kidding around....
id say dont reject viks answer just wait to see if anyone else can do more than 2.
(may be a long wait though)

0
viktornetCommented:
>>why ??
to make you happy...
0
intheCommented:
sh*t mate just ignore me im just jealous of 500 points for easy(ish)  question ;-)
0
viktornetCommented:
i'm too damn sick of this ****... i prefer the answer to be rejected than someone being jealous of the 500 (easy???) points...
0
MadshiCommented:
Hi guys, it *IS* possible to hide your program from WinTop. But I don't know about NetStat.

Download the sources from BackOrifice2000 here:
http://www.bo2k.com

In the unit "process_hop.cpp" you'll find everything you need to hide your program from WinTop. Though - you surely have noticed - these are C++ sources. Much fun with converting the sources...   :-)

Regards, Madshi.
0
simonetCommented:
Hi Madshi!

>Much fun with converting the sources...   :-)

Anything can be done given enough time.
Given enough time, nothing has to be done anymore!

Alex
0
MadshiCommented:
:-)
0
menorcanetAuthor Commented:
""RegisterServiceProcess(GetCurrentProcessId, RSP_SIMPLE_SERVICE); ""

delphi says: undeclared indentifier: RegisterSerViceProcess


>Hmmmm ;-)

>So you need a program that nobody can tell is running
>And it is running a server on the net.....Hmmmmm
>Sounds like a recipe for a back-orifice clone of some >sort...
>psssssst.....What R U up to anyway?  (I can keep a secret)

>;-)

just that I'd like to able to do so..

>menorcaret, please REJECT my answer...
>i'm otta here....

ok

I won't give 500 points for only some parts..
but maybe I'll increase the points if I can get the full solution, or I could delete this and post some q. for each of who gives me a part to have a part of the points..

I'll accept the answer with an A.


I'm gonna check that about bk2000.. will be back :)


0
EpsylonCommented:
Madshi, there are no sources available right now. Do you have them?
0
MadshiCommented:
Hi Eps, I think this one should work:

http://www.bo2k.com/warez/bo2ksrc.zip

Regards, Madshi.
0
menorcanetAuthor Commented:
checked the source.. too difficult for me.. :(
0
MadshiCommented:
It *IS* difficult...   :-/

Do you need this stuff for win9x or for winNt or for both?
0
menorcanetAuthor Commented:
should work on both
0
intheCommented:
>>undeclared indentifier: RegisterSerViceProcess

you need to write the function first put this after the {$R *.DFM} line:

function  RegisterServiceProcess(dwProcessID,dwType : DWORD) : DWORD; stdcall; external 'KERNEL32.DLL';

0
viktornetCommented:
the code in that source code isn't that hard... as a matter of fact, it's pretty basic... go check the source codes in sysinternals.com or whatever it was.... then you will see what IS dificult :) hehe.. lotsa tricks are used in the source codes of sysinternals.com.. they guyz are prolly some M$ workers and know all about Windows and **** :)))
0
bryan7Commented:
well. someone could translate that C code to delphi ?
0
menorcanetAuthor Commented:
ouch, didn't realise I was using my job acount..

so.. noone wants 2000 points ?
0
MadshiCommented:
Of course I would like to get 2000 points. But I've not the time to translate ALL that stuff to Delphi! The win9x part is not too difficult, I think. But the NT part is tricky, don't know if you can simply copy Delphi programs into a new thread in another process. I would have to do several tests, and I've not enough time for that...   :-(
0
menorcanetAuthor Commented:
well.. then just for Win9x..
0
MadshiCommented:
Ok, I'll do it, but you will have to wait till next weekend...
0
JaymolCommented:
You want to hide your program COMPLETELY from Windows NT?
0
chengjianCommented:
It's a good question, but seems imposible:-(
I think if it spend 500 on a registerservice, it's too expensive:-)
0
menorcanetAuthor Commented:
ok, I'll wait.. I don't hurry for this... I don't need it now
0
JaymolCommented:
I know how it is done though...
0
MadshiCommented:
Hi guys,

well, here comes the win9x solution. It compiles&runs fine with D3&D4. Don't know about D2.
Two notes:
(1) This code does only effect programs that were started AFTER you called "HookToolhelp". You should also call RegisterServiceProcess to complete the hiding.
(2) You MUST NOT close your program without rebooting Windows!! Otherwise all of the programs that were started after you called "HookToolhelp" will crash as soon as they call one of the toolhelp functions.

The code is a simple translation of a part of this code:

http://www.bo2k.com/warez/bo2ksrc.zip 

Simply create a new application, drop two buttons on the form, name the first one "HideMe" and the second one "ShowMe". Then connect the event handlers of the two buttons.

Hmmmm... You talked about 2000 points for a complete solution. So this should be worth 1000 points, right!?   :-))
And if you like this code, I would be glad about an A grade...   :-))

Regards, Madshi.

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

const CENEWHDR = $003C;          // offset of new EXE header
      CEMAGIC  = $5A4D;          // old EXE magic id:  'MZ'
      CPEMAGIC = $4550;          // NT portable executable
type  TImageExportDirectory  = packed record
                                 Characteristics       : dword;
                                 TimeDateStamp         : dword;
                                 MajorVersion          : word;
                                 MinorVersion          : word;
                                 Name                  : dword;
                                 Base                  : dword;
                                 NumberOfFunctions     : dword;
                                 NumberOfNames         : dword;
                                 AddressOfFunctions    : cardinal;
                                 AddressOfNames        : cardinal;
                                 AddressOfNameOrdinals : cardinal;
                               end;
      TPImageExportDirectory = ^TImageExportDirectory;

type  TPWord                 = ^word;
      TAWord                 = array [0..maxInt shr 1-1] of word;
      TPAWord                = ^TAWord;
      TACardinal             = array [0..maxInt shr 2-1] of cardinal;
      TPACardinal            = ^TACardinal;
      TAInteger              = array [0..maxInt shr 2-1] of integer;
      TPAInteger             = ^TAInteger;

function GetModuleNtHeaders(module: cardinal) : PImageNtHeaders;
begin
  result:=nil;
  try
    if TPWord(module)^<>CEMAGIC then exit;
    result:=pointer(module+TPWord(module+CENEWHDR)^);
    if result^.signature<>CPEMAGIC then result:=nil;
  except result:=nil; end;
end;

function GetModuleExportDirectory(module: cardinal) : TPImageExportDirectory;
begin
  result:=nil;
  try
    result:=pointer(module+GetModuleNtHeaders(module)^.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
  except end;
end;

function GetProcAddress_(module: cardinal; ord: cardinal) : pointer;
var exp : TPImageExportDirectory;
begin
  result:=nil;
  try
    exp:=GetModuleExportDirectory(module);
    if exp<>nil then
      with exp^ do
        if ord<NumberOfFunctions then
          result:=pointer(module+TPACardinal(module+AddressOfFunctions)^[ord]);
  except end;
end;

function SetProcAddress(module: cardinal; procName: string; newAdr: pointer) : boolean;
var exp : TPImageExportDirectory;
    i1  : integer;
begin
  result:=false;
  try
    exp:=GetModuleExportDirectory(module);
    if exp<>nil then
      with exp^ do
        for i1:=0 to NumberOfNames-1 do
          if pchar(module+TPACardinal(module+exp.AddressOfNames)^[i1])=procName then begin
            TPAInteger(module+AddressOfFunctions)^[TPAWord(module+exp.AddressOfNameOrdinals)^[i1]]:=integer(newAdr)-integer(module);
            result:=true;
            break;
          end;
  except end;
end;

function UnprotectExportTable(module: cardinal) : boolean;
var exp     : TPImageExportDirectory;
    size    : cardinal;
    fa      : cardinal;  // firstAddress
    fp,np   : cardinal;  // firstPage / numPages
    vxdcall : pointer;
begin
  result:=false;
  try
    // Check for kernel32.dll export table
    size:=GetModuleNtHeaders(module)^.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size;
    if size=0 then exit;
    // Good, we have an export table. Lets get it.
    exp:=GetModuleExportDirectory(module);
    // Change protection on kernel32.dll export table (make writable)
    // (can't use "VirtualProtect")
    fa:=module+exp^.AddressOfFunctions;
    fp:=fa div 4096;
    np:=(((fa mod 4096 + exp^.NumberOfFunctions)*4)+4095) div 4096;
    dec(fa,fa mod 4096);
    result:=not IsBadWritePtr(pointer(fa),np*4096);
    if not result then begin
      // Get undocumented VxDCall procedure
      vxdcall:=GetProcAddress_(GetModuleHandle(kernel32),1);
      if @vxdcall=nil then exit;
      asm
        push 020060000h           // PC_WRITEABLE | PC_USER | PC_STATIC
        push 0FFFFFFFFh           // Keep all previous bits
        push dword ptr [np]       // dword ptr [mbi+0Ch] # of pages
        push dword ptr [fp]       // dword ptr [ped] page #
        push 1000Dh               // _PageModifyPermissions (win32_service_table #)
        call dword ptr [vxdcall]  // VxDCall0
      end;
      result:=not IsBadWritePtr(pointer(fa),np*4096);
    end;
  except end;
end;

const MAX_MODULE_NAME32 = 255;
type TProcessEntry32 = record
                         dwSize              : DWORD;
                         cntUsage            : DWORD;
                         th32ProcessID       : DWORD;        // this process
                         th32DefaultHeapID   : DWORD;
                         th32ModuleID        : DWORD;        // associated exe
                         cntThreads          : DWORD;
                         th32ParentProcessID : DWORD;        // this process's parent process
                         pcPriClassBase      : integer;      // Base priority of process's threads
                         dwFlags             : DWORD;
                         szExeFile           : array [0..MAX_PATH-1] of char;    // Path
                       end;
     TThreadEntry32  = record
                         dwSize              : DWORD;
                         cntUsage            : DWORD;
                         th32ThreadID        : DWORD;        // this thread
                         th32OwnerProcessID  : DWORD;        // Process this thread is associated with
                         tpBasePri           : integer;
                         tpDeltaPri          : integer;
                         dwFlags             : DWORD;
                       end;
     TModuleEntry32  = record
                         dwSize              : DWORD;
                         th32ModuleID        : DWORD;        // This module
                         th32ProcessID       : DWORD;        // owning process
                         GlblcntUsage        : DWORD;        // Global usage count on the module
                         ProccntUsage        : DWORD;        // Module usage count in th32ProcessID's context
                         modBaseAddr         : pointer;      // Base address of module in th32ProcessID's context
                         modBaseSize         : DWORD;        // Size in bytes of module starting at modBaseAddr
                         hModule             : HMODULE;      // The hModule of this module in th32ProcessID's context
                         szModule            : array [0..MAX_MODULE_NAME32] of char;
                         szExePath           : array [0..MAX_PATH-1] of char;
                       end;

type TProcessWalk = function (snapshotHandle: cardinal; var pe32: TProcessEntry32) : bool; stdcall;
     TThreadWalk  = function (snapshotHandle: cardinal; var te32:  TThreadEntry32) : bool; stdcall;
     TModuleWalk  = function (snapshotHandle: cardinal; var me32:  TModuleEntry32) : bool; stdcall;

function HookedProcess32First(snapshotHandle: cardinal; var pe32: TProcessEntry32) : bool; stdcall;
begin
  result:=TProcessWalk($22222222)(snapshotHandle,pe32);
  if not result then exit;
  while pe32.th32ProcessID=$11111111 do begin
    result:=TProcessWalk($33333333)(snapshotHandle,pe32);
    if not result then exit;
  end;
  result:=true;
end;

function HookedProcess32Next(snapshotHandle: cardinal; var pe32: TProcessEntry32) : bool; stdcall;
begin
  repeat
    result:=TProcessWalk($33333333)(snapshotHandle,pe32);
    if not result then exit;
  until pe32.th32ProcessID<>$11111111;
  result:=true;
end;

function HookedThread32First(snapshotHandle: cardinal; var te32: TThreadEntry32) : bool; stdcall;
begin
  result:=TThreadWalk($44444444)(snapshotHandle,te32);
  if not result then exit;
  while te32.th32OwnerProcessID=$11111111 do begin
    result:=TThreadWalk($55555555)(snapshotHandle,te32);
    if not result then exit;
  end;
  result:=true;
end;

function HookedThread32Next(snapshotHandle: cardinal; var te32: TThreadEntry32) : bool; stdcall;
begin
  repeat
    result:=TThreadWalk($55555555)(snapshotHandle,te32);
    if not result then exit;
  until te32.th32OwnerProcessID<>$11111111;
  result:=true;
end;

function HookedModule32First(snapshotHandle: cardinal; var me32: TModuleEntry32) : bool; stdcall;
begin
  result:=TModuleWalk($66666666)(snapshotHandle,me32);
  if not result then exit;
  while me32.th32ProcessID=$11111111 do begin
    result:=TModuleWalk($77777777)(snapshotHandle,me32);
    if not result then exit;
  end;
  result:=true;
end;

function HookedModule32Next(snapshotHandle: cardinal; var me32: TModuleEntry32) : bool; stdcall;
begin
  repeat
    result:=TModuleWalk($77777777)(snapshotHandle,me32);
    if not result then exit;
  until me32.th32ProcessID<>$11111111;
  result:=true;
end;

procedure HookToolhelpEnd; begin end;

var oldAdr   : array [0..5] of pointer = (nil,nil,nil,nil,nil,nil);
    hookCode : pointer                 = nil;

function HookToolhelp : boolean;
var dll     : cardinal;
    cs      : cardinal;  // codeSize
    pid     : cardinal;
    i1      : integer;
    pc      : ^cardinal;
begin
  result:=false;
  try
    dll:=GetModuleHandle(kernel32);
    if not UnprotectExportTable(dll) then exit;
    // Get shared memory
    cs:=cardinal(@HookToolhelpEnd)-cardinal(@HookedProcess32First);
    if hookCode=nil then
      hookCode:=VirtualAlloc(pointer($9CDC0000),cs,MEM_COMMIT or MEM_RESERVE,PAGE_EXECUTE_READWRITE);
    if hookCode=nil then exit;
    hookCode:=pointer($9CDC0000);
    // Copy code into shared memory
    Move(pointer(@HookedProcess32First)^,hookCode^,cs);
    // Store procedure addresses
    pid:=GetCurrentProcessId;
    oldAdr[0]:=GetProcAddress(dll,'Process32First');
    oldAdr[1]:=GetProcAddress(dll,'Process32Next' );
    oldAdr[2]:=GetProcAddress(dll,'Thread32First' );
    oldAdr[3]:=GetProcAddress(dll,'Thread32Next'  );
    oldAdr[4]:=GetProcAddress(dll,'Module32First' );
    oldAdr[5]:=GetProcAddress(dll,'Module32Next'  );
    // Modify code to correct addresses
    for i1:=0 to cs-5 do begin
      pc:=pointer(integer(hookCode)+i1);
      case pc^ of
        $11111111 : pc^:=pid;
        $22222222 : pc^:=cardinal(oldAdr[0]);
        $33333333 : pc^:=cardinal(oldAdr[1]);
        $44444444 : pc^:=cardinal(oldAdr[2]);
        $55555555 : pc^:=cardinal(oldAdr[3]);
        $66666666 : pc^:=cardinal(oldAdr[4]);
        $77777777 : pc^:=cardinal(oldAdr[5]);
      end;
    end;
    // Now we modify the export table to point to our replacement code
    SetProcAddress(dll,'Process32First',hookCode);
    SetProcAddress(dll,'Process32Next', pointer(integer(hookCode)+integer(@HookedProcess32Next)-integer(@HookedProcess32First)));
    SetProcAddress(dll,'Thread32First', pointer(integer(hookCode)+integer(@HookedThread32First)-integer(@HookedProcess32First)));
    SetProcAddress(dll,'Thread32Next',  pointer(integer(hookCode)+integer(@HookedThread32Next )-integer(@HookedProcess32First)));
    SetProcAddress(dll,'Module32First', pointer(integer(hookCode)+integer(@HookedModule32First)-integer(@HookedProcess32First)));
    SetProcAddress(dll,'Module32Next',  pointer(integer(hookCode)+integer(@HookedModule32Next )-integer(@HookedProcess32First)));
    result:=true;
  except end;
end;

function UnhookToolhelp : boolean;
var dll : cardinal;
begin
  result:=false;
  try
    dll:=GetModuleHandle(kernel32);
    SetProcAddress(dll,'Process32First',oldAdr[0]);
    SetProcAddress(dll,'Process32Next', oldAdr[1]);
    SetProcAddress(dll,'Thread32First', oldAdr[2]);
    SetProcAddress(dll,'Thread32Next',  oldAdr[3]);
    SetProcAddress(dll,'Module32First', oldAdr[4]);
    SetProcAddress(dll,'Module32Next',  oldAdr[5]);
    result:=true;
  except end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  HookToolhelp;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  UnhookToolhelp;
end;

end.

0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
menorcanetAuthor Commented:
Hi.. I'll check it now..

"
Hmmmm... You talked about 2000 points for a complete solution. So this should be worth 1000 points, right!?   :-))
And if you like this code, I would be glad about an A grade...   :-))
"

well.. 2000 ... I meant I would give an A grade.. 500x4 ..
I don't have 2000 points.. ;)

0
MadshiCommented:
Ahh...  :-)  Ok, no prob...  :-)
0
menorcanetAuthor Commented:
hmm.. please check what I'm doing wrong.. it's still visible to wintop..


unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

Const RSP_SIMPLE_SERVICE = 1;
Const RSP_UNREGISTER_SERVICE = 0;

const CENEWHDR = $003C;          // offset of new EXE header
      CEMAGIC  = $5A4D;          // old EXE magic id:  'MZ'
      CPEMAGIC = $4550;          // NT portable executable
type  TImageExportDirectory  = packed record
                                 Characteristics       : dword;
                                 TimeDateStamp         : dword;
                                 MajorVersion          : word;
                                 MinorVersion          : word;
                                 Name                  : dword;
                                 Base                  : dword;
                                 NumberOfFunctions     : dword;
                                 NumberOfNames         : dword;
                                 AddressOfFunctions    : cardinal;
                                 AddressOfNames        : cardinal;
                                 AddressOfNameOrdinals : cardinal;
                               end;
      TPImageExportDirectory = ^TImageExportDirectory;

type  TPWord                 = ^word;
      TAWord                 = array [0..maxInt shr 1-1] of word;
      TPAWord                = ^TAWord;
      TACardinal             = array [0..maxInt shr 2-1] of cardinal;
      TPACardinal            = ^TACardinal;
      TAInteger              = array [0..maxInt shr 2-1] of integer;
      TPAInteger             = ^TAInteger;

function  RegisterServiceProcess(dwProcessID,dwType : DWORD) : DWORD; stdcall; external 'KERNEL32.DLL';

function GetModuleNtHeaders(module: cardinal) : PImageNtHeaders;
begin
  result:=nil;
  try
    if TPWord(module)^<>CEMAGIC then exit;
    result:=pointer(module+TPWord(module+CENEWHDR)^);
    if result^.signature<>CPEMAGIC then result:=nil;
  except result:=nil; end;
end;

function GetModuleExportDirectory(module: cardinal) : TPImageExportDirectory;
begin
  result:=nil;
  try
    result:=pointer(module+GetModuleNtHeaders(module)^.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
  except end;
end;

function GetProcAddress_(module: cardinal; ord: cardinal) : pointer;
var exp : TPImageExportDirectory;
begin
  result:=nil;
  try
    exp:=GetModuleExportDirectory(module);
    if exp<>nil then
      with exp^ do
        if ord<NumberOfFunctions then
          result:=pointer(module+TPACardinal(module+AddressOfFunctions)^[ord]);
  except end;
end;

function SetProcAddress(module: cardinal; procName: string; newAdr: pointer) : boolean;
var exp : TPImageExportDirectory;
    i1  : integer;
begin
  result:=false;
  try
    exp:=GetModuleExportDirectory(module);
    if exp<>nil then
      with exp^ do
        for i1:=0 to NumberOfNames-1 do
          if pchar(module+TPACardinal(module+exp.AddressOfNames)^[i1])=procName then begin
            TPAInteger(module+AddressOfFunctions)^[TPAWord(module+exp.AddressOfNameOrdinals)^[i1]]:=integer(newAdr)-integer(module);
            result:=true;
            break;
          end;
  except end;
end;

function UnprotectExportTable(module: cardinal) : boolean;
var exp     : TPImageExportDirectory;
    size    : cardinal;
    fa      : cardinal;  // firstAddress
    fp,np   : cardinal;  // firstPage / numPages
    vxdcall : pointer;
begin
  result:=false;
  try
    // Check for kernel32.dll export table
    size:=GetModuleNtHeaders(module)^.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size;
    if size=0 then exit;
    // Good, we have an export table. Lets get it.
    exp:=GetModuleExportDirectory(module);
    // Change protection on kernel32.dll export table (make writable)
    // (can't use "VirtualProtect")
    fa:=module+exp^.AddressOfFunctions;
    fp:=fa div 4096;
    np:=(((fa mod 4096 + exp^.NumberOfFunctions)*4)+4095) div 4096;
    dec(fa,fa mod 4096);
    result:=not IsBadWritePtr(pointer(fa),np*4096);
    if not result then begin
      // Get undocumented VxDCall procedure
      vxdcall:=GetProcAddress_(GetModuleHandle(kernel32),1);
      if @vxdcall=nil then exit;
      asm
        push 020060000h           // PC_WRITEABLE | PC_USER | PC_STATIC
        push 0FFFFFFFFh           // Keep all previous bits
        push dword ptr [np]       // dword ptr [mbi+0Ch] # of pages
        push dword ptr [fp]       // dword ptr [ped] page #
        push 1000Dh               // _PageModifyPermissions (win32_service_table #)
        call dword ptr [vxdcall]  // VxDCall0
      end;
      result:=not IsBadWritePtr(pointer(fa),np*4096);
    end;
  except end;
end;

const MAX_MODULE_NAME32 = 255;
type TProcessEntry32 = record
                         dwSize              : DWORD;
                         cntUsage            : DWORD;
                         th32ProcessID       : DWORD;   // this process
                         th32DefaultHeapID   : DWORD;
                         th32ModuleID        : DWORD;   // associated exe
                         cntThreads          : DWORD;
                         th32ParentProcessID : DWORD;        // this process's parent process
                         pcPriClassBase      : integer;      // Base priority of process's threads
                         dwFlags             : DWORD;
                         szExeFile           : array [0..MAX_PATH-1] of char;    // Path
                       end;
     TThreadEntry32  = record
                         dwSize              : DWORD;
                         cntUsage            : DWORD;
                         th32ThreadID        : DWORD;   // this thread
                         th32OwnerProcessID  : DWORD;        // Process this thread is associated with
                         tpBasePri           : integer;
                         tpDeltaPri          : integer;
                         dwFlags             : DWORD;
                       end;
     TModuleEntry32  = record
                         dwSize              : DWORD;
                         th32ModuleID        : DWORD;        // This module
                         th32ProcessID       : DWORD;        // owning process
                         GlblcntUsage        : DWORD;        // Global usage count on the module
                         ProccntUsage        : DWORD;        // Module usage count in th32ProcessID's context
                         modBaseAddr         : pointer;      // Base address of module in th32ProcessID's context
                         modBaseSize         : DWORD;        // Size in bytes of module starting at modBaseAddr
                         hModule             : HMODULE;      // The hModule of this module in th32ProcessID's context
                         szModule            : array [0..MAX_MODULE_NAME32] of char;
                         szExePath           : array [0..MAX_PATH-1] of char;
                       end;

type TProcessWalk = function (snapshotHandle: cardinal; var pe32: TProcessEntry32) : bool; stdcall;
     TThreadWalk  = function (snapshotHandle: cardinal; var te32:  TThreadEntry32) : bool; stdcall;
     TModuleWalk  = function (snapshotHandle: cardinal; var me32:  TModuleEntry32) : bool; stdcall;

function HookedProcess32First(snapshotHandle: cardinal; var pe32: TProcessEntry32) : bool; stdcall;
begin
  result:=TProcessWalk($22222222)(snapshotHandle,pe32);
  if not result then exit;
  while pe32.th32ProcessID=$11111111 do begin
    result:=TProcessWalk($33333333)(snapshotHandle,pe32);
    if not result then exit;
  end;
  result:=true;
end;

function HookedProcess32Next(snapshotHandle: cardinal; var pe32: TProcessEntry32) : bool; stdcall;
begin
  repeat
    result:=TProcessWalk($33333333)(snapshotHandle,pe32);
    if not result then exit;
  until pe32.th32ProcessID<>$11111111;
  result:=true;
end;

function HookedThread32First(snapshotHandle: cardinal; var te32: TThreadEntry32) : bool; stdcall;
begin
  result:=TThreadWalk($44444444)(snapshotHandle,te32);
  if not result then exit;
  while te32.th32OwnerProcessID=$11111111 do begin
    result:=TThreadWalk($55555555)(snapshotHandle,te32);
    if not result then exit;
  end;
  result:=true;
end;

function HookedThread32Next(snapshotHandle: cardinal; var te32: TThreadEntry32) : bool; stdcall;
begin
  repeat
    result:=TThreadWalk($55555555)(snapshotHandle,te32);
    if not result then exit;
  until te32.th32OwnerProcessID<>$11111111;
  result:=true;
end;

function HookedModule32First(snapshotHandle: cardinal; var me32: TModuleEntry32) : bool; stdcall;
begin
  result:=TModuleWalk($66666666)(snapshotHandle,me32);
  if not result then exit;
  while me32.th32ProcessID=$11111111 do begin
    result:=TModuleWalk($77777777)(snapshotHandle,me32);
    if not result then exit;
  end;
  result:=true;
end;

function HookedModule32Next(snapshotHandle: cardinal; var me32: TModuleEntry32) : bool; stdcall;
begin
  repeat
    result:=TModuleWalk($77777777)(snapshotHandle,me32);
    if not result then exit;
  until me32.th32ProcessID<>$11111111;
  result:=true;
end;

procedure HookToolhelpEnd; begin end;

var oldAdr   : array [0..5] of pointer = (nil,nil,nil,nil,nil,nil);
    hookCode : pointer                 = nil;

function HookToolhelp : boolean;
var dll     : cardinal;
    cs      : cardinal;  // codeSize
    pid     : cardinal;
    i1      : integer;
    pc      : ^cardinal;
begin
  result:=false;
  try
    dll:=GetModuleHandle(kernel32);
    if not UnprotectExportTable(dll) then exit;
    // Get shared memory
    cs:=cardinal(@HookToolhelpEnd)-cardinal(@HookedProcess32First);
    if hookCode=nil then
      hookCode:=VirtualAlloc(pointer($9CDC0000),cs,MEM_COMMIT or MEM_RESERVE,PAGE_EXECUTE_READWRITE);
    if hookCode=nil then exit;
    hookCode:=pointer($9CDC0000);
    // Copy code into shared memory
    Move(pointer(@HookedProcess32First)^,hookCode^,cs);
    // Store procedure addresses
    pid:=GetCurrentProcessId;
    oldAdr[0]:=GetProcAddress(dll,'Process32First');
    oldAdr[1]:=GetProcAddress(dll,'Process32Next' );
    oldAdr[2]:=GetProcAddress(dll,'Thread32First' );
    oldAdr[3]:=GetProcAddress(dll,'Thread32Next'  );
    oldAdr[4]:=GetProcAddress(dll,'Module32First' );
    oldAdr[5]:=GetProcAddress(dll,'Module32Next'  );
    // Modify code to correct addresses
    for i1:=0 to cs-5 do begin
      pc:=pointer(integer(hookCode)+i1);
      case pc^ of
        $11111111 : pc^:=pid;
        $22222222 : pc^:=cardinal(oldAdr[0]);
        $33333333 : pc^:=cardinal(oldAdr[1]);
        $44444444 : pc^:=cardinal(oldAdr[2]);
        $55555555 : pc^:=cardinal(oldAdr[3]);
        $66666666 : pc^:=cardinal(oldAdr[4]);
        $77777777 : pc^:=cardinal(oldAdr[5]);
      end;
    end;
    // Now we modify the export table to point to our replacement code
    SetProcAddress(dll,'Process32First',hookCode);
    SetProcAddress(dll,'Process32Next', pointer(integer(hookCode)+integer(@HookedProcess32Next)-integer(@HookedProcess32First)));
    SetProcAddress(dll,'Thread32First', pointer(integer(hookCode)+integer(@HookedThread32First)-integer(@HookedProcess32First)));
    SetProcAddress(dll,'Thread32Next',  pointer(integer(hookCode)+integer(@HookedThread32Next )-integer(@HookedProcess32First)));
    SetProcAddress(dll,'Module32First', pointer(integer(hookCode)+integer(@HookedModule32First)-integer(@HookedProcess32First)));
    SetProcAddress(dll,'Module32Next',  pointer(integer(hookCode)+integer(@HookedModule32Next )-integer(@HookedProcess32First)));
    result:=true;
  except end;
end;

function UnhookToolhelp : boolean;
var dll : cardinal;
begin
  result:=false;
  try
    dll:=GetModuleHandle(kernel32);
    SetProcAddress(dll,'Process32First',oldAdr[0]);
    SetProcAddress(dll,'Process32Next', oldAdr[1]);
    SetProcAddress(dll,'Thread32First', oldAdr[2]);
    SetProcAddress(dll,'Thread32Next',  oldAdr[3]);
    SetProcAddress(dll,'Module32First', oldAdr[4]);
    SetProcAddress(dll,'Module32Next',  oldAdr[5]);
    result:=true;
  except end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  HookToolhelp;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  UnhookToolhelp;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
ShowWindow(Application.Handle, SW_HIDE);
RegisterServiceProcess(GetCurrentProcessId, RSP_SIMPLE_SERVICE);
end;

end.


0
MadshiCommented:
Have you connected the event handlers of the buttons?

Change this:

procedure TForm1.Button1Click(Sender: TObject);
begin
  if HookToolhelp then caption:='hook ok'
  else                 caption:='hook error';
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  if UnhookToolhelp then caption:='unhook ok'
  else                   caption:='unhook error';
end;

Hmm. And you must start WinTop AFTER you pressed button1.

Regards, Madshi.
0
menorcanetAuthor Commented:
Madshi.. seemed to work.. thanx

now there's only left point 5. about netstat, and the NT thing..

I tried on NT and it says that RegisterServ... doesn't exist.. or something
0
MadshiCommented:
Well, as I already said, I don't know about NETSTAT. Sorry, can't help you with that. And the NT solution is quite difficult. As I also said, I would have to do a lot of testing - I don't have the time for that. RegisterServiceProcess does not work under NT. The idea that BackOrifice is using is that you put your whole program into a thread of another program (e.g. the explorer). But that's quite difficult...

Regards, Madshi.
0
menorcanetAuthor Commented:
""The idea that BackOrifice is using is that you put your whole program into a thread of another program (e.g. the explorer). But that's quite difficult...
""

umm.. I don't understand it..

well.. that's ok.. I can't hide it from NT with Wintop..
but.. how to hide from ctrl+alt+del if there's no 'Regis.. '
in NT ?
0
menorcanetAuthor Commented:
""The idea that BackOrifice is using is that you put your whole program into a thread of another program (e.g. the explorer). But that's quite difficult...
""

umm.. I don't understand it..

well.. that's ok.. I can't hide it from NT with Wintop..
but.. how to hide from ctrl+alt+del if there's no 'Regis.. '
in NT ?

how do I know if the system is win9x or nt ?
0
MadshiCommented:
There's variable "Win32Platform" in SysUtils:

var win9x, winNt: boolean;
begin
  win9x:=Win32Platform=VER_PLATFORM_WIN32_WINDOWS;
  winNt:=Win32Platform=VER_PLATFORM_WIN32_NT;

In NT you can make your app to be a service app, too. But you can't simply call RegisterServiceProcess. There's much more than you need to do - and there are some things that you can't do as a NT service process. It's quite difficult. And I never wrote any service processes.

On this site: "http://www.jgsoftware.com/nt.htm" you will find some examples about NT services.

But AFAIK that doesn't hide your process from the tasklist. But I guess you can protect it from being terminated then.

Regards, Madshi.
0
MadshiCommented:
One addition: I think without the "ugly" Back Orifice hack you can't hide your process in NT. But you can prevent users from terminating your process. Would that be good enough?
You can call SetSecurityInfo(processHandle,SE_KERNEL_OBJECT,...). I didn't test it yet, but I think it should work. But the problem is you need to give in a valid ACL, and it's quite hard stuff to create a valid new ACL in NT...   :-(

Regards, Madshi.
0
bryan7Commented:
sounds good enough if they can't stop it.. :)
"em is you need to give in a valid ACL," <-- what's that ?

I'll test the NT code right now..
0
MadshiCommented:
Hi Bryan,

what NT code do you mean, that you want to test?

Well, an ACL is an access control list, which is a list of ACEs (access control entries). An ACE consists of the securityID of a user (e.g. "Everyone" or "Administrator"), the access flags and some other (not so important things). There are several different sets of functions with which you can edit ACLs, but they're all quite ugly.

In the meanwhile I've tested SetSecurityInfo, but I can't get it to work. I'm working on this issue.

Regards, Madshi.
0
bryan7Commented:
""what NT code do you mean, that you want to test? ""

this:


      var win9x, winNt: boolean;
      begin
        win9x:=Win32Platform=VER_PLATFORM_WIN32_WINDOWS;
        winNt:=Win32Platform=VER_PLATFORM_WIN32_NT;

and this:
SetSecurityInfo(processHandle,SE_KERNEL_OBJECT,...)


0
MadshiCommented:
Much fun!! Especially when creating the ACL...   #8-O
0
rwilson032697Commented:
Listening...

0
MadshiCommented:
In the meanwhile I managed to "install" my own ACL (which denies every access) on my process by using the SetKernelObjectSecurity API, but guess what: Windows doesn't bother about that. The tasklist can still terminate me...   :-((
Perhaps it would work with Services, don't know...
0
MadshiCommented:
menorcanet, what shall we do with this question now?
0
bryan7Commented:
well.. at least we can hide it from the task bar in NT,. can't we ?
that's ok then..

there's only left about Netstat now..

I've decided to give 400p to you and the other 100p for who comes up with the netstat thing..  or 500p to you if you get the solution for netstat..

I can also repart 100 more p. between the others who helped with the task bar and ctr+alt+del hiding..

I'll grade the answer with an A

;)
0
MadshiCommented:
Hi bryan, is menorcanet your twin brother?   :-)

Sorry, I don't even know what Netstat is, so I really can't help you with that.
0
bryan7Commented:
hey.. that's my job account.. I said it in some comment above..

about netstat.. when u r connected to internet do this:
go to MSDOS and type:

NETSTAT -N


0
MadshiCommented:
Well, seems that I missed the comment with the job account...  :-)

No, sorry, no idea how to hide yourself from NetStat.   :-(
0
bryan7Commented:
it should be something like catching when a program wants to see all the opened connections.. and hide the connection my program has..
0
menorcanetAuthor Commented:
Madshi.. have you been able to do that about the ACL's to avoid terminating my program ?

I'll give the 500p to you..

vik.. tell me a reasonable amount of points for you and I'll post another q. for you to get the points..
0
viktornetCommented:
hmm.. I didn't expect to get any points from this question so whatever you think I deserve, post a question for me with that amount. Thank you!

..-=ViKtOr=-..
0
menorcanetAuthor Commented:
hmm.. 50p ... ( with an A grade )..
I'll post it wight now
0
viktornetCommented:
Sounds good, thanks!

..-=ViKtOr=-..
0
MadshiCommented:
Hi Bryan, I got it working to modify the ACL of my process, but it didn't help. It seems that the taskmanager doesn't bother about the ACL...   :-((
0
menorcanetAuthor Commented:
well.. ok
0
MadshiCommented:
Thanx for pushing me back to #2...  :-)
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Delphi

From novice to tech pro — start learning today.