Harici DLL'den Method çağırmak. Bir debugging öyküsü... (2)

Yazdığınız makaleleri ve üyelerimizin işine yarayacağını düşündüğünüz kodlarınızı gönderebilirsiniz. Bu foruma soru sormayın!
Cevapla
fduman
Moderator
Mesajlar: 2749
Kayıt: 17 Ara 2004 12:02
Konum: Ankara

Harici DLL'den Method çağırmak. Bir debugging öyküsü... (2)

Mesaj gönderen fduman »

Arkadaşlar. Bir önceki makalemden sonra bu iş böyle mi kaldı? Hayır kalmadı. Bu sefer de Object ile class değerlerine ulaşamadım. Yöntem işime yaramadı. Bunun da nedeni Self parametresinin bu yöntemle ortadan uçması. DLL tabii ki benim Self pointer'imi bilmiyor. Benim method'u çağırırken de parametre olarak geçemiyordu. Ancak Self parametresi bir object için olmazsa olmaz bir değer. Object için ayrılmış belleğin lokasyonu Self'te tutuluyor. Object kendi içinde class variable'lara ulaşırken Self pointer üzerinden ulaşıyor.

Örnek vermek gerekirse:

Kod: Tümünü seç

type
  TMyClass = class(TObject)
  private
    FValue: Longword;
  public
    function GetValue(Handle: Longword): Longword; stdcall;
  end;

function TMyClass.GetValue(Handle: Longword): Longword;
begin
  Result:= Self.FValue;
end;
Bu örnekte GetValue method'u FValue değerini geri döndürür. FValue değerinin bellek lokasyonu Self pointer'ının değeri baz alınarak belirlenir. Bunun nedeni şu. Siz bu class'ı kullanarak 3 object yarattınız diyelim. Bu 3 object'in FValue değerinin farklı bellek lokasyonlarında saklanması gerekir ki herbir object farklı değerler taşıyabilsin. Bunun için TMyClass.Create yapıp objeye bellek ayırıyoruz. Eğer DLL'den GetValue methodunu makalede anlattığım yöntemle çağırsaydım, method FValue değerine ulaşamayıp access violation hatası verecekti. Çünkü Self parametresi tanımlı değil.

Ben de bunun üzerine daha nefis bir yöntem hackledim. Hackledim diyorum çünkü başka bir componentin uyguladığı yöntemi aldım. Componentin source'u olmadığından debugger'a güvendim. Assembler modunda trace ederek adamların yöntemini çözdüm. Aslında oldukça basit ve zekice bir yöntemdi...

Adamlar Self pointer'ın içeriğini önceden bellekte saklıyor, daha sonra bu pointer'ı stack a push edip method call gerçekleştiriyor. Bunun için şuna benzer bir wrapper yazmışlar.

Kod: Tümünü seç

pop edx               // Handle parametresi stack'ten alınıyor.
mov eax, Self       
push eax              // İlk parametre olarak Self stack'e koyuluyor.
push edx              // Handle parametresi stack'e koyuluyor.
jmp TMyClass.GetValue // method jump yapılıyor.
Bu kodda Self yerine object'i create ettiğinizde dönen pointer'ı koymalısınız. Method jump yapılan yerde method'un jump offset'ini hesaplamalısınız. Görece kolay. (Method'un pointer'i - wrapper kodunun pointer'i - wrapper'in kodunun size'ı) ile hesaplayabilirsiniz.

Bu jump kodunu neden static vermedik diyecek olursanız, wrapper stub kodunu oluşturup bellekte yer ayırıyoruz. Ayrılan bellek adresi hep aynı olmadığından jump offset te hep değişecektir. Bu yüzden stub koduna yer ayırdıktan sonra hesaplanması gerekir.

Ben stub'ı şu şekilde oluşturmayı tercih ettim:

Kod: Tümünü seç

type
  TStubRecord = packed record
    pop_edx: Byte;
    mov_eax: Byte;
    SelfPtr: Pointer;
    push_eax: Byte;
    push_edx: Byte;
    jmp_near: Byte;
    MethodOffset: Pointer;
  end;

procedure CreateStub;
begin
// Stub'a bellek ayır.
GetMem(FStub, SizeOf(TStubRecord));
with TStubRecord(FStub^) do
begin
  // Burada instruction opcode'larını yazıyoruz.
   pop_edx:= $5A;          // Pop EDX
   mov_eax:= $B8;          // Mov EAX, FFunction
  // Self'i de koyduk.
   SelfPtr:= FSelfPtr;
   push_eax:= $50;         // Push EAX
   push_edx:= $52;         // Push EDX
   jmp_near:= $E9;         // Jmp FMethodPtr
   // Method'a sıçrama adresini hesaplar
   MethodOffset:= Pointer(Integer(FMethodPtr) - Integer(FStub) -
     SizeOf(TStubRecord));
  end;
end;
İşte bu kod Handle parametresini alıyor. Self parametresini ilk parametre olarak stack'e atıp Handle parametresini de koyduktan sonra Method'a sıçrıyor. Çok zekice ve basit. DLL'e de bu stub kodunun pointer'ini vermeniz DLL'in bu koda call etmesini sağlıyor. Yani bu stub Delphi'nin otomatik olarak halletiği ilk parametre olarak Self verilmesi gibi işlemleri simule ediyor. Umarım işinize yarar. Yaşasın hacking..
Cevapla