Hallo guys lama tak bersuah nih :D. Pada rindu yah sharingan code dari saya ? :p. Oke yang rindu sya cerita” duluyah tentang menghilangnya dan sekarang kegiatan apa :p..

Kira” pada bulan januari 11 bulan yang lalu, saya diterima pada suatu perusahaan consultan IT yang bergerak pada pengembangan aplikasi-aplikasi pada suatu perusahaan. Seiring dengan di terimanya itu saya diharuskan belajar banyak yang sebelumnya sya tidak dapatkan saat aktive di pengembangan lowlevel. Misalnya pengembangan aplikasi database, pengimplementasian system dan yang penting adalah businis model dari perusahaan (diluar proggraming). Hihihi hanya itu yang bisa kuceritakan tentang kegiatanku sekarang..

BacktoTopik, Dulu saya membuat aplikasi crypter (you know for what :P) yang menggunakan beberapa fungsi yang tidak biasa, atau bisa dibilang sangat lowlevel. Fungsi yang membuat windows api yang saya gunakan pada aplikasi tidak bisa dihook pada usermode. Saya sebut fungsi ini “Union Api” (begitu nama code dari orang di forum gamedeception.

Apa itu “Union Api” ?. Seperti kita ketahui pada usermode semua windows api (kernel32, advapi32) akan berujung ke ntdll, dan fungsi itu sangat rentan di hook oleh aplikasi lain baik metode patching IAT (import adresss table), EAT (Export adress table), inline hooking, hooking lainnya. Untuk mencegah hall itu kita mensimulasikan apa yang dilakukan windows dengan mensimulasikan pemanggilan syscall. Karena pembahasannya akan panjang dan lebih baik anda cari referensi sendiri tentang syscall ini.

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


Here u goo my Union Api

{ U_UnionApi
  Author: Abhe
  Description: Anti Hook NTDLL API
  Release Date: 1 December 2011
  Website: https://cybercoding.wordpress.com/
  History: Thanks method from GameDeception, not remember who.. 😀
}


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:

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;
Advertisements