C'de Integer Diziye String Yerleştirmek

Merhaba arkadaşlar,

Programlama dersinde can sıkıntısı ile boğuşurken birden "integer diziye char veya string gömebilir miyim?", "integer alanına string yerleştirsem 4 byte'lık alan taşar mı?" gibisinden birşeyler geldi aklıma.Merakım üzerine bunu denedim ve oldu da.Derlerken Warning verse de kodlar tam istediğim gibi çalıştı ve ekrana string bir değer bastı.

Bunu nasıl yaptığını merak ederek üstüne düştüm, Kenan abinin Assembly serisinden kaptığım birkaç bilgi ile.C'de yazdığım uygulamayı gdb ile reverse engineering yaparak incelemeye başladım.İzlediğim yolu da adım adım anlatayım size.

Öncelikle integer bir diziye integer bir değer girerek derleyelim kodumuzu ve aradaki farkı anlayabilmek için normal şartlarda bu durum nasıl işliyormuş bakalım;

#include <stdio.h>

int main(){ int dizi[10];

dizi[0] = 1879;
printf("%d\n", dizi[0]);

return 1955;

}

Kodumuzu gcc ile derleyelim;
$ gcc stringInInt.c -o stringInInt
Şimdi gdb ile işleyişine bakalım kodların, normal şartlarda bir diziye değer yerleştirince neler oluyor;
   0x000000000040052d <+0>: push   rbp
   0x000000000040052e <+1>:   mov    rbp,rsp
   0x0000000000400531 <+4>:   sub    rsp,0x30
=> 0x0000000000400535 <+8>:    mov    DWORD PTR [rbp-0x30],0x757
   0x000000000040053c <+15>:mov    eax,DWORD PTR [rbp-0x30]
   0x000000000040053f <+18>:mov    esi,eax
   0x0000000000400541 <+20>:mov    edi,0x4005e4
   0x0000000000400546 <+25>:mov    eax,0x0
   0x000000000040054b <+30>:call   0x400410 <printf@plt>
   0x0000000000400550 <+35>:mov    eax,0x7a3
   0x0000000000400555 <+40>:leave
   0x0000000000400556 <+41>:ret
Yukarıda ki kodda da gördüğünüz gibi, $rbp'nin 0x30(48) byte altına 0x757 değerini taşıyor.Nedir bu 0x757? Hexadecimal olan 0x757'yi integer'a çevirdiğimiz zaman 1879 sayısı ile karşılaşıyoruz.Daha sonra da devam eden işlemlerde de görebileceğiniz üzere bu değeri, önce $eax'a sonra da $esi'ye taşıyor.<+30> yazan satırda da printf fonksiyonumuzu call edip bu değeri ekrana yazıyor.En sonda <+35>te çıkış değerimizi(return 1955)'i hexadecimal olarak(0x7a3) $eax'a atıyor ve programdan çıkıyor.

Normal şartlarda durum böyle ilerliyor, şimdi de asıl olayımıza gelelim.Integer diziye string yerleştirip derleyelim yukarıda ki aynı gcc komutu ile.

#include <stdio.h>

int main(){ int dizi[10];

dizi[0] = "ahmetkotan.com.tr";
printf("%s\n", dizi[0]);

return 1955;

}

Şimdi assembly ile kodları inceleyelim tekrardan;
   0x000000000040052d <+0>: push   rbp
   0x000000000040052e <+1>:   mov    rbp,rsp
   0x0000000000400531 <+4>:   sub    rsp,0x30
=> 0x0000000000400535 <+8>:    mov    eax,0x4005e4
   0x000000000040053a <+13>:mov    DWORD PTR [rbp-0x30],eax
   0x000000000040053d <+16>:mov    eax,DWORD PTR [rbp-0x30]
   0x0000000000400540 <+19>:mov    esi,eax
   0x0000000000400542 <+21>:mov    edi,0x4005f6
   0x0000000000400547 <+26>:mov    eax,0x0
   0x000000000040054c <+31>:call   0x400410 <printf@plt>
   0x0000000000400551 <+36>:mov    eax,0x7a3
   0x0000000000400556 <+41>:leave
   0x0000000000400557 <+42>:ret
Dikkatli izleyici abi anlıyor hemen :) Neyse yine anlatayım, imlecin olduğu satıra bakınca zaten gözünüze direk çarpacaktır.Bu sefer ilk değer atamasını(0x4005e4) $rbp'nin 48 byte altına değil, $eax değişkenine yapıyor.Daha sonrasında da üstte ki işlemlerin aynısı sırasıyla devam ediyor.$rbp'nin altına ve ordan tekrar $eax registerına atılıyor.Burda ki değere(0x4005e4) bakacak olursak;
(gdb) x/s 0x4005e4
0x4005e4:   "ahmetkotan.com.tr"
"ahmetkotan.com.tr" stringini ordan oraya ordan oraya taşıyor ve bir şekilde bellekte tutuyor.Burada ki işlem fazlalığını tersine mühendislik alanında ki uzman abilerimiz/arkadaşlarımız yorumlarda açıklarsa daha mutlu olabiliriz diye düşünüyorum, çünkü çok fazla bi tersine mühendislik bilgim yok benimde.Yalan yanlış bilgilerle doldurmayayım boşuna buraları.Daha sonrasında da aynı üstte ki kod gibi <+31>'de printf fonksiyonunu call edip değeri ekrana yazıyor ve en sonda da yine return değerimiz olan 1955'i $eax'a yazıp programı kapatıyor.

Velhasıl kelam, o kadar uğraştım ettim tam olarak istediğimi alamasamda merak ettiğim şeyi başardığıma inanıyorum ve aralarında ki farkı bulabildim.Dediğim gibi bilgili abilerimiz/arkadaşlarımız var ise durumu yorumlarda açıklayabilirler.Gerekirse yazıya edit geçerim.

İyi çalışmalar..


Tags: c programming, c string, embed string, reverse engineering