Penulis Topik: Union Api - Call Native Api using syscall  (Dibaca 912 kali)

Offline meong

  • Pro100
  • ****
  • Tulisan: 121
  • Reputation: 203
    • Lihat Profil
Union Api - Call Native Api using syscall
« pada: Desember 01, 2012, 08:33:37 PM »
Hey guys, longtime not check this forum.. I'm not code a security aplication now.. So thingking for sharing some old code..

This unit used in my old crypter, called it MegaCrypter. Main idea is to use syscall for call native api so hard or imposible to hook in userland.

some reference :
http://www.nynaeve.net/?p=48
http://blog.oxff.net/#2sapnfkthvpzjscp3xwq
or just search google with keyword syscall, sysenter, or etc

btw here u go my unit

Kode: [Pilih]
{ U_UnionApi
  Author: Abhe
  Description: Anti Hook NTDLL API
  Release Date: 1 December 2011
  Website: http://cybercoding.wordpress.com/
  History: Thanks method from GameDeception, not remember who.. :D
}


unit U_UnionApi;

interface
uses
Windows;

var
  pSystemCall: Pointer;
  WOW32Reserved: Cardinal;
  Ntdll: Pointer;
  SysNumber : DWORD;

function strlenA(const s: PAnsiChar): cardinal;
function LazyLoadPe(szFilename:PWideChar):Pointer;
Function GetSysNumber(ApiHash : DWORD):Word;overload;
Function GetSysNumber(ApiName : AnsiString):Word; overload;
function ExGetmoduleHandle(mhash: Cardinal): THANDLE;
function ExGetmoduleFileName(mhash: Cardinal): PWideChar;

function ApiStub: DWORD; stdcall;

{32}
function ApiCall32(Number : DWORD; Arg1: Pointer): DWORD; stdcall; overload;
function ApiCall32(Number : DWORD; Arg1, Arg2: Pointer): DWORD; stdcall; overload;
function ApiCall32(Number : DWORD; Arg1, Arg2, Arg3: Pointer): DWORD; stdcall; overload;
function ApiCall32(Number : DWORD; Arg1, Arg2, Arg3, arg4: Pointer): DWORD; stdcall; overload;
function ApiCall32(Number : DWORD; Arg1, Arg2, Arg3, arg4, Arg5: Pointer): DWORD; stdcall; overload;
function ApiCall32(Number : DWORD; Arg1, Arg2, Arg3, arg4, arg5, Arg6: Pointer): DWORD; stdcall; overload;
function ApiCall32(Number : DWORD; Arg1, Arg2, Arg3, arg4, arg5, Arg6, Arg7: Pointer): DWORD; stdcall; overload;
function ApiCall32(Number : DWORD; Arg1, Arg2, Arg3, arg4, arg5, Arg6, Arg7, Arg8: Pointer): DWORD; stdcall; overload;
function ApiCall32(Number : DWORD; Arg: Array of Const): DWORD; stdcall; overload;
function ApiCall32(ApiName: AnsiString; Arg: Array of Const): DWORD; stdcall; overload;
implementation

function strlenA(const s: PAnsiChar): cardinal;
asm
  mov edx, edi
  mov edi, eax
  or ecx, -1
  xor eax, eax
  repne scasb
  dec eax
  dec eax
  sub eax, ecx
  mov edi, edx
end;

function adler32(adler: cardinal; buf: pointer; len: cardinal): cardinal;
asm
    push      ebx
    push      esi
    push      edi
    mov       edi,eax
    shr       edi,16
    movzx     ebx,ax
    push      ebp
    mov       esi,edx
    test      esi,esi
    mov       ebp,ecx
    jne       @31
    mov       eax,1
    jmp       @32
@31:
    test      ebp,ebp
    jbe       @34
@33:
    cmp       ebp,5552
    jae        @35
    mov       eax,ebp
    jmp        @36
@35:
    mov       eax,5552
@36:
    sub       ebp,eax
    cmp       eax,16
    jl        @38
    xor       edx,edx
    xor       ecx,ecx
@39:
    sub       eax,16
    mov       dl,[esi]
    mov       cl,[esi+1]
    add       ebx,edx
    add       edi,ebx
    add       ebx,ecx
    mov       dl,[esi+2]
    add       edi,ebx
    add       ebx,edx
    mov       cl,[esi+3]
    add       edi,ebx
    add       ebx,ecx
    mov       dl,[esi+4]
    add       edi,ebx
    add       ebx,edx
    mov       cl,[esi+5]
    add       edi,ebx
    add       ebx,ecx
    mov       dl,[esi+6]
    add       edi,ebx
    add       ebx,edx
    mov       cl,[esi+7]
    add       edi,ebx
    add       ebx,ecx
    mov       dl,[esi+8]
    add       edi,ebx
    add       ebx,edx
    mov       cl,[esi+9]
    add       edi,ebx
    add       ebx,ecx
    mov       dl,[esi+10]
    add       edi,ebx
    add       ebx,edx
    mov       cl,[esi+11]
    add       edi,ebx
    add       ebx,ecx
    mov       dl,[esi+12]
    add       edi,ebx
    add       ebx,edx
    mov       cl,[esi+13]
    add       edi,ebx
    add       ebx,ecx
    mov       dl,[esi+14]
    add       edi,ebx
    add       ebx,edx
    mov       cl,[esi+15]
    add       edi,ebx
    add       ebx,ecx
    cmp       eax,16
    lea       esi,[esi+16]
    lea       edi,[edi+ebx]
    jge       @39
@38:
    test      eax,eax
    je         @42
@43:
    xor       edx,edx
    mov       dl,[esi]
    add       ebx,edx
    dec       eax
    lea       esi,[esi+1]
  lea       edi,[edi+ebx]
    jg        @43
@42:
    mov       ecx,65521
    mov       eax,ebx
    xor       edx,edx
    div       ecx
    mov       ebx,edx
    mov       ecx,65521
    mov       eax,edi
    xor       edx,edx
    div       ecx
    test      ebp,ebp
    mov       edi,edx
    ja        @33
@34:
    mov       eax,edi
    shl       eax,16
    or        eax,ebx
@45:
@32:
    pop       ebp
    pop       edi
    pop       esi
    pop       ebx
end;

function LazyLoadPe(szFilename:PWideChar):Pointer;
var
  hFile:    DWORD;
  dwSize:   DWORD;
  dwNull:   DWORD;
  temp:     Pointer;
  IDH:      PImageDosHeader;
  INH:      PImageNtHeaders;
  ISH:      PImageSectionHeader;
  i:        WORD;
begin
  result := nil;
  hFile := CreateFileW(szFilename, GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, 0, 0);
  if (hFile = INVALID_HANDLE_VALUE) then exit;
  dwSize := GetFileSize(hFile, nil);
  GetMem(temp, dwSize);
  if not ReadFile(hFile, temp^, dwSize, dwNull, nil) then exit;
  IDH := temp;
  INH := Pointer(Integer(temp) + IDH^._lfanew);
  GetMem(Result, INH^.OptionalHeader.SizeOfImage);
  ZeroMemory(Result, INH^.OptionalHeader.SizeOfImage);
  CopyMemory(Result, temp, INH^.OptionalHeader.SizeOfHeaders);
  for i := 0 to INH^.FileHeader.NumberOfSections - 1 do begin
    ISH := Pointer(Integer(temp) + IDH^._lfanew + 248 + i * 40);
    CopyMemory(Pointer(DWORD(Result) + ISH^.VirtualAddress), Pointer(DWORD(temp) + ISH^.PointerToRawData), ISH^.SizeOfRawData);
  end;
  FreeMem(temp, dwSize);
  CloseHandle(hFile);
end;

function GetPEB(): Pointer;
asm
  mov eax, large fs:30h
  retn
end;

function ExGetmoduleHandle(mhash: Cardinal): THANDLE;
var
  x , f, cur  : DWORD;
  Hash        : Cardinal;
begin
  result := 0;
  x := DWORD(GetPEB);
  if (mhash = 0) then begin
    result := PDWORD(x+8)^;
    exit;
  end;
  x := PDWORD(x+$C)^;
  f := x+$14;
  cur := PDWORD(f)^;
  while (cur <> f) do begin
    x := cur - $8;
    Hash := adler32(0, Pointer(PDWORD(x+$30)^), PWORD(x+$2c)^);
    if (hash=mhash) then begin
      result := PDWORD(x+$18)^;
      exit;
    end;
    cur := PDWORD(cur)^;
  end;
end;

function ExGetmoduleFileName(mhash: Cardinal): PWideChar;
var
  x , f, cur  : DWORD;
  Hash        : Cardinal;
begin
  result := nil;
  x := DWORD(GetPEB);
  x := PDWORD(x+$C)^;
  f := x+$14;
  cur := PDWORD(f)^;
  while (cur <> f) do begin
    x := cur - $8;
    Hash := adler32(0, Pointer(PDWORD(x+$30)^), PWORD(x+$2c)^);
    if (hash=mhash) then begin
      result := PWidechar(Pointer(PDWORD(x+$28)^));
      exit;
    end;
    cur := PDWORD(cur)^;
  end;
end;

function ExGetProcAddress(hModule: THANDLE; phash: Cardinal): Pointer;
var
  pINH: PImageNtHeaders;
  pIDD: PImageDataDirectory;
  pIED: PImageExportDirectory;
  pdwFuncs1, pdwFuncs: PULONG;
  pdwNames: PULONG;
  pdwOrdinals: PWORD;
  dwOrd1: DWORD;
  i, k: cardinal;
  apiname:PAnsiChar;
  hash :Cardinal;
begin
  result := nil;
  pINH := PImageNtHeaders(Cardinal(hModule) + Cardinal(PImageDosHeader(hModule)^._lfanew));
  pIDD := PImageDataDirectory(Cardinal(@pINH^.OptionalHeader.DataDirectory) + IMAGE_DIRECTORY_ENTRY_EXPORT);
  pIED := PImageExportDirectory(ULONG(hModule) + pIDD^.VirtualAddress);
  pdwFuncs := PULONG(ULONG(hModule) + Cardinal(pIED^.AddressOfFunctions));
  pdwNames := PULONG(ULONG(hModule) + Cardinal(pIED^.AddressOfNames));
  pdwOrdinals := PWORD(ULONG(hModule) + Cardinal(pIED^.AddressOfNameOrdinals));
  pdwFuncs1 := pdwFuncs;
  for i := 0 to pIED^.NumberOfNames - 1 do begin
    dwOrd1 := pdwOrdinals^;
    k := 0;
    pdwFuncs := pdwFuncs1;
    while (k < dwOrd1) do begin
      inc(pdwFuncs);
      inc(k);
    end;
    if (pdwFuncs^ < pIDD^.VirtualAddress) or (pdwFuncs^ >= pIDD^.VirtualAddress + pIDD^.Size) then begin
      apiname := PAnsiChar(hModule + pdwNames^);
      hash := adler32(0, apiname, strlenA(apiname));
      if (hash = phash) then begin
        result := Pointer(ULONG(hModule) + pdwFuncs^);
        exit;
      end;
    end;
    inc(pdwOrdinals);
    inc(pdwNames);
  end;
end;

Function GetSysNumber(ApiHash : DWORD):Word;
var
  Addr : Pointer;
begin
  Addr := ExGetProcAddress(Cardinal(Ntdll), ApiHash);
  result := PWord(NativeUint(Addr)+1)^
end;

Function GetSysNumber(ApiName : AnsiString):Word;
var
  Hash : Cardinal;
begin
  hash := adler32(0, Pansichar(apiname), Length(apiname));
  result := GetSysNumber(hash);
end;

//
// Manual System Call Api
//
function IsWow:NativeUint; stdcall;
asm
  xor   eax, eax
  mov   eax, fs:[eax+$18] //teb
  mov   eax, [eax+$C0] //WOW32Reserved
end;

function bSysenterAvailable: Bool;
asm
  XOR EAX, EAX
  CPUID
  BT EDX, 11
  db $D6 //SALC
end;

procedure INT2;
asm
  LEA EDX, [ESP+8]
  INT $2E
end;

procedure SYSENTER;
asm
  MOV EDX, ESP
  SYSENTER
end;

procedure WowCall;
asm
  xor ecx,ecx
  lea edx,[esp+4]
  call dword ptr fs:[$0C0]
end;

Procedure InitSysCall;
begin
  WOW32Reserved := IsWow;
  {check if sysenter availabe, use int2 if not}
  if not bSysenterAvailable then pSystemCall := @INT2
  else pSystemCall := @SYSENTER;
  if Boolean(WOW32Reserved) then pSystemCall := @WowCall;
end;

function ApiStub: DWORD; stdcall;
asm
  POP EBP
  mov edi, dword ptr [esp]
  mov dword ptr [esp+4], edi
  add esp, 4
  push eax
  call IsWow;
  mov edi, eax
  pop eax
  dec edi
  jns @F1
  xor EDI, EDI
  call pSystemCall
  jmp @f2
@F1:
  xor EDI, EDI
  jmp pSystemCall
@F2:
  //PUSH EBP
end;

function ApiCall32(Number : DWORD; Arg1: Pointer): DWORD; stdcall;
asm
  jmp ApiStub;
end;

function ApiCall32(Number : DWORD; Arg1, Arg2: Pointer): DWORD; stdcall;
asm
  jmp ApiStub;
end;

function ApiCall32(Number : DWORD; Arg1, Arg2, Arg3: Pointer): DWORD; stdcall;
asm
  jmp ApiStub;
end;

function ApiCall32(Number : DWORD; Arg1, Arg2, Arg3, arg4: Pointer): DWORD; stdcall;
asm
  jmp ApiStub;
end;

function ApiCall32(Number : DWORD; Arg1, Arg2, Arg3, arg4, Arg5: Pointer): DWORD; stdcall;
asm
  jmp ApiStub;
end;

function ApiCall32(Number : DWORD; Arg1, Arg2, Arg3, arg4, arg5, Arg6: Pointer): DWORD; stdcall;
asm
  jmp ApiStub;
end;

function ApiCall32(Number : DWORD; Arg1, Arg2, Arg3, arg4, Arg5, Arg6, Arg7: Pointer): DWORD; stdcall;
asm
  jmp ApiStub;
end;

function ApiCall32(Number : DWORD; Arg1, Arg2, Arg3, arg4, arg5, Arg6, Arg7, Arg8: Pointer): DWORD; stdcall;
asm
  jmp ApiStub;
end;

function ApiCall32(Number : DWORD; Arg: Array of Const): DWORD; stdcall;
begin
  case length(arg) of
    1 : result := ApiCall32(Number, Arg[0].VPointer);
    2 : result := ApiCall32(Number, Arg[0].VPointer, Arg[1].VPointer);
    3 : result := ApiCall32(Number, Arg[0].VPointer, Arg[1].VPointer, Arg[2].VPointer);
    4 : result := ApiCall32(Number, Arg[0].VPointer, Arg[1].VPointer, Arg[2].VPointer, Arg[3].VPointer);
    5 : result := ApiCall32(Number, Arg[0].VPointer, Arg[1].VPointer, Arg[2].VPointer, Arg[3].VPointer, Arg[4].VPointer);
    6 : result := ApiCall32(Number, Arg[0].VPointer, Arg[1].VPointer, Arg[2].VPointer, Arg[3].VPointer, Arg[4].VPointer, Arg[5].VPointer);
    7 : result := ApiCall32(Number, Arg[0].VPointer, Arg[1].VPointer, Arg[2].VPointer, Arg[3].VPointer, Arg[4].VPointer, Arg[5].VPointer, Arg[6].VPointer);
    8 : result := ApiCall32(Number, Arg[0].VPointer, Arg[1].VPointer, Arg[2].VPointer, Arg[3].VPointer, Arg[4].VPointer, Arg[5].VPointer, Arg[6].VPointer, Arg[7].VPointer);
    else result := 0;
  end;
end;

function ApiCall32(ApiName: AnsiString; Arg: Array of Const): DWORD; stdcall;
begin
  result := ApiCall32(GetSysNumber(ApiName), Arg);
end;


initialization
  Ntdll := LazyLoadPe(ExGetmoduleFileName($240C0388));
  InitSysCall;
finalization
  FreeMem(Ntdll);
end.

contoh penggunaan:
Kode: [Pilih]
function ExOpenProcess(dwDesiredAccess: DWord; Id : DWord):THANDLE;
var
  hProcess: THANDLE;
  attr: OBJECT_ATTRIBUTES;
  cli: CLIENT_ID;
begin
  InitializeObjectAttributes(@attr, nil, 0, 0, nil);
  cli.UniqueProcess := THandle(Id);
  cli.UniqueThread := 0;
  result := 0;
  if NtSuccess(ApiCall32('NtOpenProcess', [@hProcess, dwDesiredAccess, @attr, @cli])) then result := hProcess
end;

function Antidebug1:boolean;
var
  h:Thandle;
begin
  result := false;
  h := ExOpenProcess(PROCESS_ALL_ACCESS, CsrGetProcessId);
  if h<>0 then begin
    result := true;
    ApiCall32('NtClose', [h]); //NtClose
  end;
end;

btw link to my blog http://cybercoding.wordpress.com/2012/12/01/union-api/