30 Mart 2016 Çarşamba

Builder-Stub Tekniği

Burada anlatılacak Builder-Stub tekniğinin Resource kullanımı ile gerçekleştirilmesidir.kısaca builder stub dan bahsetmek gerekirse; elinizde bir takım bilgiler var bu bilgileri builder aracılığı ile stub dosyanıza yazıyor/yerleştiriyorsunuz,stub kendine eklenen bu bilgiyi alıyor/okuyor ve işliyor.





Builder içerisinde kullanıcağımız APIler:
BeginUpdateResource,UpdateResource,EndResource

Stub içerisinde kullanıcağımız APIler :
FindResource,SizeofResouce,LoadResource,LockResource

API,İşletim sistemlerinin size açtığı fonksiyonlardır.Bunların prototipleri bilinir.yukarıdaki fonksiyonların prototipler şu şekildedir:


HANDLE WINAPI BeginUpdateResource(
  _In_ LPCTSTR pFileName,
  _In_ BOOL    bDeleteExistingResources
);
 
BeginUpdateResource WINAPI si bize,UpdateResource tarafından Kaynak ekleme,silme,
yer değiştirme işlemleri yapabileceğimiz bir handle döner.

peki handle nedir? prosesin handle tablosuna index olarak geçirilir.handle sayesinde işletim
sistemi kaynağa ilişkin olayları takip edebilir.


 
pFileName,üzerinde Resource işlemleri yapıcağınız dosya bu parametreye geçirilir.
bDeleteExistingResources,pFileName ait olan kaynakların silinip/silinmeyeceğini buradan 
bildirebilirsiniz.eğer bu parametreye true verilirse,diğer resourcelar silinir.örneğin bu değer
true olursa VERSION INFO ve MANIFEST gibi bilgiler exe file da silinir.
 
BOOL WINAPI UpdateResource(
  _In_     HANDLE  hUpdate,
  _In_     LPCTSTR lpType,
  _In_     LPCTSTR lpName,
  _In_     WORD    wLanguage,
  _In_opt_ LPVOID  lpData,
  _In_     DWORD   cbData
); 
 
UpdateResource,PE dosyası içerisindeki kaynağa ekler,siler veya değişiklik uygular.biz burada
belirli bir ham data gömme işlemi yapıcaz.
 
Kısaca parametrelerini tanıyacak olursak.
 
hUpdate,BeginUpdateResource tarafından dönülen handle bu parametreye geçirilir.
lpType,Resource tipi bu parametreyle belirtir.MAKEINTRESOURCE(ID) makrosuyla C dilinde ilgili
tip geçirilebilir.Resource türler belirlidir.biz bu parametreye RT_RCDATA geçiricez,
RAW Data olarak bilinir,türkçesi ham veridir.

lpName,Resource'unuzun ismini keyfi olarak seçip bu parametreye geçiririz.örneğin "Kernsteinist".
 
wLanguage,üzerinde işlem yapıcağımız kaynağın Language Identifierını belirtir.
meraklılarına şöyle açıklayabilirim,Language Identifier ülke ya da bölge için tanımlanmış
uluslararası standart bir sayıdır.Her bir dil 16-bitlik Unique ID(kendisine has eşsiz)sahiptir.
 
+-------------------------+-------------------------+
| SubLanguage ID  | Primary Lang ID   |
+-------------------------+-------------------------+
15                    10  9                         0   bit
 
yukarıdaki gibi tanımlanır.
 
PrimaryLanguage dili belirtirken SubLanguage ise ülke veya bölgeyi belirtir.Bir dilin
birden fazla ülkede konuşulmasından dolayı bu şekilde tanımlanmıştır.
 
lpData,Kaynağa eklenecek veriyi byte dizi olarak bu parametreye geçiriyoruz.
cbData,Kaynağa eklenecek verinin boyutunu belirtiyoruz.
 
 
BOOL WINAPI EndUpdateResource(
  _In_ HANDLE hUpdate,
  _In_ BOOL   fDiscard
);
 
hUpdate,BeginUpdateResource'un döndüğü handle bu parametreye geçiriyoruz.
fDiscard,Yaptıklarımızın dosyaya yazılıp/yazılmayacağını belirtir,bu parametre false girilirse
belirtiğimiz işlemler yapılır ve Resource(RT_RCDATA) belirttiğimiz datayla exe dosyasına gömülmüş olur.true değerinde yaptıklarımız exe file uygulanmaz.

YUKARIDA ANLATILANLAR BUİLDER İÇERİSİNDE UYGULAYACAKLARIMIZ.



HRSRC WINAPI FindResource(
  _In_opt_ HMODULE hModule,
  _In_     LPCTSTR lpName,
  _In_     LPCTSTR lpType
);
Bu fonksiyon stub içerisinde yer alacak.belirttiğimiz lpName(Resource'un ismi),lpType(Resource'un Türü) ile kaynağın yerini belirten bir handle döner.eğer 0 dönerse aradığımız resource bulunamadı.


DWORD WINAPI SizeofResource(
  _In_opt_ HMODULE hModule,
  _In_     HRSRC   hResInfo
);

Tahmin edebileceğiniz gibi Resource boyunun bilgisini buradan elde ederiz.bize Resource'un boyutunu döner.
 hResInfo,bulunan kaynağı işaret eden handle buraya geçirilir.FindResource tarafından dönülen handle değeridir.


HGLOBAL WINAPI LoadResource(
  _In_opt_ HMODULE hModule,
  _In_     HRSRC   hResInfo
);

parametreleri SizeofResource ile aynı.Belirtilen kaynağın memorydeki ilk bytenı işaret eden adresi elde etmek için kullanabileceğimiz bir handle bize getirir.(HGLOBAL)


LPVOID WINAPI LockResource(
  _In_ HGLOBAL hResData
);

LoadResource bize getirdiği handle değerini buraya geçiririz,eğer kaynak mevcutsa bize Resource'un ilk bytenı işaret eden bir pointer döner.kaynak mevcut değilse NULL değer döner.

Bu arada Parametreleri tanımlayan ifadelere macar notasyonu denir(Hungarian Notation)
Bu notasyona ilişkin bir kaç örnek vereyim:

 
LPCTSTR  = Long Pointer To a Constant TCHAR STRing,yani const char*
WORD       = 16 bit,2 byte olarak bilinir.
LPVOID     = Long Pointer VOID,yani Void*



Bu kadar bilgiden sonra C# dilinde bu işin gerçekleştirilmesi şöyledir :

BUİLDER CODE :


    class Program
    {


        //GetLastError fonksiyonunu kullanıcaksanız SetLastError=True yapmalısınız.
        //Marshal.GetLastWin32Error() ile API üzerinde meydana gelmiş hataya ilişkin kodu alabilirsiniz.
        //Created By Kernsteinist
        [DllImport("kernel32.dll", SetLastError = true)]
        public static extern IntPtr BeginUpdateResource(string pFileName,bool bDeleteExistingResources);

        [DllImport("kernel32.dll", SetLastError = true)]
        public static extern bool UpdateResource(IntPtr hUpdate, string lpType, string lpName, ushort wLanguage, byte[] lpData, uint cbData);

        [DllImport("kernel32.dll", SetLastError = true)]
        public static extern bool EndUpdateResource(IntPtr hUpdate, bool fDiscard);

       static byte[] Convert_To_Byte(string to_be_added)
        {
            byte[] to_byte = new byte[to_be_added.Length];

            for (int i = 0; i < to_be_added.Length; i++)
            {
                char c = to_be_added[i];
                to_byte[i] = (byte)c;

            }

            return to_byte;
        }


        static void Main(string[] args)
        {


            Console.WriteLine("Enter anything value :");
            string to_be_added = Console.ReadLine();

            File.Copy("STUB.EXE", "Kernsteinist.EXE",true);
           

            IntPtr hUpdate = BeginUpdateResource("Kernsteinist.exe", false);
            bool error = UpdateResource(hUpdate,"RT_RCDATA", "Kern", 0, Convert_To_Byte(to_be_added),(uint)to_be_added.Length);
            if (!error)
            {
                Console.WriteLine("Error...");
                Console.WriteLine(Marshal.GetLastWin32Error());
                EndUpdateResource(hUpdate, true);
            }
            else
            {
                EndUpdateResource(hUpdate, false);
                Console.WriteLine("Succesful...");
               
            } } }
STUB CODE :

   unsafe class Program
    {
         
            [DllImport("kernel32.dll", SetLastError = true)]
            public static extern IntPtr FindResource(int hModule, string lpName, string lpType);

            [DllImport("kernel32.dll", SetLastError = true)]
            public static extern int SizeofResource(int hModule, IntPtr hResInfo);

            [DllImport("kernel32.dll", SetLastError = true)]
            public static extern IntPtr LoadResource(int hModule, IntPtr hResInfo);


            [DllImport("kernel32.dll", SetLastError = true)]
            public static extern IntPtr LockResource(IntPtr hResData);



   
        static void Main(string[] args)
        {           

           IntPtr HRSRC = FindResource(0, "Kern", "RT_RCDATA");
           int size = SizeofResource(0, HRSRC);
           IntPtr hResData = LoadResource(0, HRSRC);
           IntPtr s = LockResource(hResData);

            byte* b = (byte*)(s); //Resource'un ilk bytenın adresi.
          

            Console.WriteLine("......");
            for (int i = 0; i < size; i++)
            {
                byte data1 = (byte)*(b+i);              
                Console.Write(data1.ToString()+" ");
              
            }

            Console.WriteLine("......");

            for (int i = 0; i < size; i++)
            {
                byte data1 = (byte)*(b + i);        
                Console.Write((char)data1);
             }
        }       
    }

Unsafe,Keywordu pointer kullanmamıza izin verilmesi için kullanmamız gereken keyword.
Projectinizin üzerine gelip sağ tıklayıp properties,daha sonra sol tarafta build tıklayın ve "Allow
Unsafe Code" seçin.


EOF

Hiç yorum yok:

Yorum Gönder