Vizacc C++ Formatter v1.0

bUG FiXeR
Program Url: www.vizacc.com
Program Tipi:
Programlama aracı
     Araçlar: SoftIce, IceDump
Basit (x )  Orta ( )  Zor ( )  Pro ( )


Başlangıç

Program VC++ ile yazılmış, program C/C++ kaynak kodlarını düzenleyerek güzel görünmelerini sağlıyor.
Yazı

Program açılışta mesajbox ile karşılıyor.Tamam butonuna tıkladıktan sonra program çalışıyor. Program 15 gün kullanım sınırlaması ile geliyor ve program kalan günleri sayarken bunun sayacını registryde tutuyor. İsterseniz bu registry anahtarını sildiğinizde program yeniden 15 gün daha kullanılabiliyor ama bizim maksadımız bu değil.Programın kalbine ulaşacağız :)

Programı keşfederken kullanılacak araçlar; Softice,icedump, ImpRec ve isteğe bağlı olarak w32Dasm.Başlıyoruz. Bu noktada softiceın yüklenmiş olduğunu ve daha sonra en yakın arkadaşı icedumpun da kullandığınız softice versiyonuna bağlı olarak çalıştırılmış olduğunu kabul ediyorum. Evet hazırsanız başlıyalım, ama hemen söyliyeyim, bu program AsProtect ile korunuyor ve bu benim ilk unpack denemem. Bu programı kırarken Mr.Stop un "DzSoft Perl Editor" yazısını daha önceden okumuş olmanızı daha iyi anlamanız için tavsiye ederim. Aslında bana kalırsa Mr.Stop'un yazısının hemen tüm Asprotect korumaları için ortak yöntem olduğu kanısındayım. Zaten bazı alıntılar yapacağım, her iki yazıyı birlikte değerlendirirseniz bu AsProtect koruması için ne kadar yeterli bilgiye sahip olduğunuzu "kendiniz de" uyguladıktan sonra anlarsınız. Burada özellikle Mr.Stop olmak üzere uzatmadan tüm buna benzer yazılarla bilgilerini paylaşanlara teşekkürler.

Hadi eğlenceye devam :) AsProtect ile korunan bu programda uygun bir noktadan başlayabilmek için softice ile uygun bir breakpoint koymalıyız.

[bpx GetDiskFreeSpaceA] -> programı çalıştır.

Kernel32 deyiz. bir kez F11 yapıyoruz. Şimdi şöyle bir noktadayız

015F:006BECDC  8B75F0              MOV ESI,[EBP-10]               <- Buradayız.
015F:006BECDF  0FAF75E4            IMUL ESI,[EBP-1C]
015F:006BECE3  0FAF75E8            IMUL ESI,[EBP-18]
015F:006BECE7  8BC3                MOV     EAX,EBX
015F:006BECE9  BA08000000          MOV EDX,00000008
015F:006BECEE  E81D48FFFF          CALL    006B3510
015F:006BECF3  8BC3                MOV     EAX,EBX
015F:006BECF5  E81247FFFF          CALL    006B340C
015F:006BECFA  8B55F4              MOV EDX,[EBP-0C]
015F:006BECFD  8910                MOV     [EAX],EDX
015F:006BECFF  8BC3                MOV     EAX,EBX
015F:006BED01  E80647FFFF          CALL    006B340C
015F:006BED06  83C004              ADD     EAX,04
015F:006BED09  8930                MOV     [EAX],ESI
015F:006BED0B  5E                  POP     ESI
015F:006BED0C  5B                  POP     EBX
015F:006BED0D  8BE5                MOV     ESP,EBP
015F:006BED0F  5D                  POP     EBP
015F:006BED10  C3                  RET

Şimdi iki defa F12. Neden iki? Çünkü bir defa daha F12 yaparsak yeniden Kernel e, bir daha yaparsak softiceden çıkıyor ve programa düşüyoruz da ondan .Burada maksat programa giriş yapılan noktaya mümkün olduğunca yakın olmak. Böylece az sonra kullanacağımız icedumpun TRACEX komutunu kullanırken zamandan ve bana kalırsa kilitlenmelerden uzak kalacağız(so far so bad :) Şimdi programa giriş yapıldığı noktayı yani Orijinal Entry Point (OEP) dediğimiz noktayı bulmalıyız. Zira program unpack edildiğinde Asprotect'siz kendi başına OEP i (ve bazı importların yerini)bulamaz, bunu onun yerine biraz sonra biz yapacağız(ImpRec ile), önce icedump ile OEP i bulalım.Burada bir açıklama daha yapayım, şu anda tracex komutunu uygulamadan önce arka planda çalışan,antivirus v.s hizmet programlarını kapatın. Çünkü sistem kararsız hale gelebiliyor ve resetlemekten başka çare kalmıyor. Sistemin kilitlendiğini anlamak için tracex komutunu verip softice ın tekrar çalışmasını beklerken fareyi hareket ettirin veya benzeri birşey, zira softice açılacak diye saatlerce bekleyebilirsiniz ama, meğer sistem kilitlenmiş olabilir en azından bende kilitlendi ve ilkinde 15 dak. softice in açılmasını bekledim(nereden bileyim bu ilk denememdi :) Şimdi [bc *] yapıyoruz. Ve, [map32 Vizcbb] deyip bu programın header bilgilerine bakıyoruz.

:map32 vizcbb

Owner     Obj Name  Obj#  Address        Size
Type
VIZCBB              0001  0167:00401000  00027000 IDATA RW
VIZCBB              0002  0167:00428000  00008000 IDATA RW
VIZCBB              0003  0167:00430000  00007000 IDATA RW
VIZCBB    .rsrc     0004  0167:00437000  00007000 IDATA RW
VIZCBB    vizacc    0005  0167:0043E000  0000E000 IDATA RW
VIZCBB    .data     0006  0167:0044C000  00001000 IDATA RW

burada bizi ilgilendiren ilk iki section adresi(401000 ve 428000). Çünkü gerçek OEP %99 programlarda ilk iki section arasında bir yerde olur. şimdi bunu kullanalım.

/Tracex 401000 428000

yazıp enterliyoruz. (İşte bu komuttan sonra softice dan çıkılıyor ama arka planda trace olayı sürüyor.Şimdi sistemin kilitlenme ihtimali var. Az önce bahsetmiştim. Biraz fare ile oynayın! Korkmayın ondan, sevgi gösterin :)Evet eğer benden şanslı iseniz ilk seferde program açılırken gelen mesajbox belirmeye başlıyor, aman! OK butonu belirince hemen tıklayın. Ben gecikince bile kilitlenmeye yüz tutuyor. Heh! Ooouuuvvvv ! evreka! softice a düştük yeniden. Şükürler olsun. Şu gelen görüntüye bakın;

015F:0040CAA1  C3                  RET
015F:0040CAA2  55                  PUSH    EBP         <- Burası OEP !
015F:0040CAA3  8BEC                MOV     EBP,ESP
015F:0040CAA5  6AFF                PUSH    FF
015F:0040CAA7  68C8A54200          PUSH    0042A5C8
015F:0040CAAC  6894184100          PUSH    00411894
015F:0040CAB1  64A100000000        MOV     EAX,FS:[00000000]
015F:0040CAB7  50                  PUSH    EAX
015F:0040CAB8  64892500000000      MOV     FS:[00000000],ESP
015F:0040CABF  83EC58              SUB     ESP,58
015F:0040CAC2  53                  PUSH    EBX

Nerden anladım orası olduğunu? Birincisi, bir çok OEP bu şekilde stack a EBP registerinin saklanmasıyla başlar. Tabii başka şeyler de var ama bu biraz göz aşinalığı. Bir şekilde pack edilmemiş, herhangi dille yazılmış programları disassemble edin ve disassmblerdan size oep i göstermesini kibarca rica edin ve şöyle alıcı gözüyle hangi komutlarla başlamış bir bakın, sonra hemen birkaçına daha, neye benzemesi gerektiğini anlarsınız. Çoğu birbirine benzer. İkincisi de, eğer tracex komutunu bir daha, bir daha deneseniz de aynı yerde kalıyorsunuz. Sanırım gayet açık oldu! Ben de bunları yeni öğrendiğim için taze taze söyliyim dedim. Özellikle yeniler için yazdım.Evet sıra geldi diske dump etmeye...

/Option P i0

yapıyoruz. Neden mi? Çünkü bu komut bize dump dan önce icedumpun default olarak yapmak isteyeceği import tablosunu yeniden oluşturma işinden vazgeçmesini söyler! Eğer bunu yapmadan "/pedump" komutunu uygularsak, kendisi zaten bunu yapamayacak ve dump edemeyecek :( sebebi ise AsProtect in import tablosunu bozup, kendi kotrolüne alması. AsProtect olmayan bir dump ise importlarının en az bir kaçı olmayan (ve bir de OEP i belirsiz)dump demektir. Importları imprec ile zaten düzenlemek zorundayız! Şimdi OEP imiz 40CAA2 de idi. Imagebase hariç OEP ise, 40CAA2 - 400000 = CAA2 olduğunu hesapladık.

/Pedump 400000 CAA2 C:\Vizac_dump.exe

diyoruz. İşte kuzu kuzu geldiiii. Şu anda C:\ kökünde "Vizac_dump.exe" diye AsProtectsiz ve Importsuz! bir dosyamız var. O orada dursun. Siz şimdi hemen orijinal dosyayı çalıştırın. Çalışıyor di mi? Sakın ola dump edilen dosyayı çalıştırmayı denemeyin, o zaten çalışmış olsa işi burada keseriz :). Sıra geldi import tablosunu düzenlemeye. Import Reconstructor programını da çalıştırın, Attach To Active Process listesinden Vizcbb.exe yi seçin. IAT AutoSearch butonuna tıklayın. Olmadı mı? Eğer Imported Functions Found kısmında Kernel, User, Advapi gibi hiç DLL yoksa, yukarıda bulduğumuz OEP için CAA2 yi OEP yazan kutucuğa girin ve tekrar IAT Autosearch e tıklayın. Şimdi ImpRec bir mesajbox ile RVA ve Size kutucuklarına girilmesi için iki değer öneriyor olmalı, bunları not edin. Get Import butonuna tıklayın. Eğer hala tanıdık DLL lerden oluşan bir liste yoksa bu not ettiğiniz değerleri gerekli kutucuklara girip, tekrar Get Import butonuna tıklayın. Eh artık olmuştur! Şimdi bir kez de Auto Trace butonuna tıklayın. Bu işimizi biraz daha kolaylaştıracak. Show Invalid e tıklayıp bir bakalım hangileri bozukmuş. Eğer şimdi Save Tree ye tıklarsanız bu listeyi text dosya halinde kaydedecektir. Bu text dosyayı açarsanız bazılarında adresler ve dll isimleri, bazı satırlarda ise ? vardır ama DLL karşılığı yoktur. İşte biz bunların ne olduklarını bulacağız.

0	000280F4	?	0000	006BC960
0	0002815C	?	0000	006BC968
0	000281A4	?	0000	006BC950
0	0002824C	?	0000	006BC928
0	000284C0	?	0000	00428D98

bu listeyi kaydettiğim text dosyadan seçip koydum. Burada daha önce bahsettiğim, Mr.Stop un "DzSoft Perl Editor" yazısını okursanız daha iyi anlarsınız. Ben de oradan alıntı yapacağım.

---------------------------------------Mr.Stop------------------------------------------------------------

...Asprotect zekice bir şey yapıyor.Program başlamadan önce Asprotect bazı apileri çalıştırıp onların dönen değerlerini bir yerde saklıyor.Daha sonra program bu apilerden birini istediğinde apiyi çağırmak yerine ilk başta bulduğu dönen değerleri yolluyor.Bu değerleri saklanan apiler şunlar.

GetModuleHandleA GetVersion GetCurrentProcess GetcurrentProcessId GetCommandlineA

SoftICE a geçiyoruz ve bpx GetVersion ile breakpoint koyuyoruz....

----------------------------------------Mr.Stop--------------------------------------------------------------

Evet, aynen öyle yapalım. [bpx GetVersion] ile bpx koyun. Şimdi programı çalıştırın. Bir kez F11 ile Kernel den dönüyoruz.Ve şunlar görünüyor;

015F:006BC7BE  E8897CFFFF          CALL KERNEL32!GetModuleHandleA
015F:006BC7C3  A34C366C00          MOV [006C364C],EAX
015F:006BC7C8  E8977CFFFF          CALL KERNEL32!GetVersion
015F:006BC7CD  A344366C00          MOV [006C3644],EAX
015F:006BC7D2  68AC356C00          PUSH    006C35AC
015F:006BC7D7  E8907CFFFF          CALL KERNEL32!GetVersionExA
015F:006BC7DC  E83B7CFFFF          CALL KERNEL32!GetCurrentProcess
015F:006BC7E1  A348366C00          MOV [006C3648],EAX
015F:006BC7E6  E8397CFFFF          CALL KERNEL32!GetCurrentProcessId
015F:006BC7EB  A350366C00          MOV [006C3650],EAX
015F:006BC7F0  E81F7CFFFF          CALL KERNEL32!GetCommandLineA
015F:006BC7F5  A340366C00          MOV [006C3640],EAX
015F:006BC7FA  C3                  RET

burada adresler farklı olabilir ama görecekleriniz böyledir :) Şimdi Mr.Stop un yazısından biraz farklı deyişle anlatayım. Teknik detay için oraya göz atın. Şu anda yapacağımız şey şu, az önce bulduğumuz bozuk importların listesinden, 6BC960, 6BC968 ... şeklindeki adreslere bakıcaz, şu üstteki durduğumuz noktada iken "u" komutu ile bunları "un-assamble" edeceğiz. Her defasında sofice in code bölümünün en üst satırlarında gördüğümüz köşeli parantez içinde görünen bellek adreslerini bir yere not edeceğiz. Şimdi daha önce de verdiğim liste için işimize yarayacak sayılar alttaki listede gösterdiğim sütundakiler.

						   Bu Sütun!
						   ---------
0	000280F4	?	0000	006BC960      > için,	 u 006BC960
0	0002815C	?	0000	006BC968	  > için,	 u 006BC968
0	000281A4	?	0000	006BC950	  > için,	 u 006BC950
0	0002824C	?	0000	006BC928	  > için,	 u 006BC928
0	000284C0	?	0000	00428D98      > için,	 u 00428D98

diyerek "un-assamble" edeceğiz. gösterdiğim sutundaki tüm adresler için aynı şey tekrarlanacak. Yukarıda fonksiyon ve içinde bulunduğu DLL i listelediğim noktaya GetVersion ile geldikten sonra sutundaki tüm sayıları u ile un-assamble edeceğiz. Şunu yapın; bpx GetVersion -> programı çalıştır -> 1 kez F11. Şu anda bir üstteki "fonksiyonlu" listedeki yerdesiniz. Sütundaki her bir adres için tek tek "U" ile bakıyoruz. Alttakiler görülecek, her un-assable a karşılık, aşağıda parantez içindeki adresleri bir yere yazın, lazım olacak. Ben kendiminkileri yazdım.

u 006BC960

mov eax, [006C3640]				<- CALL KERNEL32!GetCommandLineA
ret
-------------------------
u 006BC968

push ebp						<- CALL    KERNEL32!LockResource
mov ebp, esp
mov eax, [ebp+08]
pop ebp
ret 0004
-------------------------
u 006BC950

mov eax, [006C3648]				<- CALL KERNEL32!GetCurrentProcess
ret
-------------------------
u 006BC928

mov eax, [006C3644]				<- CALL    KERNEL32!GetVersion
ret
-------------------------
u 428D98

INVALID							<- tahmininiz ?
-------------------------

Evet u ile un-assamble edince köşeli parantez içindekiler tanıdık gelmiş olmalı. İki tanesi hariç diğerleri fonksiyonlardan dönen değerlerin saklanmış olduğu adresler. Şimdi not ettiğiniz o kağıda bir bakın. Neyi "u" lamışız; 006BC960, peki parantez içinde ne varmış? [006C3640]. Hmm peki yukarıda GetVersion ile geldiğimiz yerdeki listeye bir bakın [006C3640] değeri hangi fonksiyonun işlendiği satırın altında ?

015F:006BC7F0  E81F7CFFFF          CALL KERNEL32!GetCommandLineA
015F:006BC7F5  A340366C00          MOV [006C3640],EAX               <<<< **

Evet, GetCommandLineA nın dönen değeri saklanıyormuş. O halde 006BC960 için importun ne olduğunu öğrendik. Bunu Import Reconstructor da "Module" için Kernel32, "Function" için GetCommandLineA olacağını öğrendik. Diğerlerini de ben yukarıda bulup yanlarına yazdım. Siz de deneyin karşılaştırın. Demek biz şimdi ne yaptık? text dosyaya savelediğimiz listedeki ? li bölümlerdeki adreslerde, hangi import fonksiyonundan dönen değerlerin saklandığını öğrendik. Burada bir tanesinde (KERNEL32!LockResource) biraz diğerlerinden farklı idi. Bu da Mr.Stop un o yazısından öğrendiğim bir şey. Söyliyenin yalancısıyım desem hakkaten yalan olur çünkü, yazdığı doğru, zira bu import bizde de böyle çalışıyor :)

Sonuncu ise un-assamble ettiğimiz adresin diğerlerinden ne kadar uzak olduğundan da belli, sileceğimiz bir import, neyin nesi bilmem... Şimdi bunları bir yere not ettiyseniz artık son kısıma geldik, yani orijinal dosyadaki bozuk importları yenileri ile değiştirip, dump ettiğimiz dosyaya ekleme kısmı. Eğer Import ReConstructor u kapattıysanız yeniden orijinal dosyayı açıp, biraz bozuk da olsa oluşmuş listeyi tekrar oluşturmalısınız. Ya da Load Tree ile save ettiğiniz dosyayı yükleyin. Neyse listeden herhangi bir DLL adı içermeyen bozuk importlarımızdan birinin üzerine çift tıklayın. İki girişi olan bir kutu belirecek, üsttekine (Module)listeden gereken DLL dosyasının adını, alttakine ise(Function), yine listesinden bu importa ait olan fonksiyon ismini seçip, RVA sına da köşede yazan değere bakarak emin olduktan sonra OK tıklayın. Hepsi için(bizde 4 tane) aynısını uygulayın. En sonuncusunu ise söylemiştim sileceğiz, sağ klik -> Delete Thunk(s). Tamam şimdi dananın kuyruğu kopuyor ve bu uzun yazı da bitiyor :) Fix Dump a tıklayın ve sorulunca Dump ettiğimiz dosyayı seçin. Evet herşeyi kapattım ben, sıra geldi denemeye, dump ettiğimiz yerde bir tane fazladan dosya bulacaksınız, bu import tablosu oluşturulmuş, son exe dosyası. Bi çalıştıralım bakalım. Eyyyoooo ! çalışıyor. Ne açılışta gelen mesajbox kaldı ne de zaman sınırlaması. Bu iş de böylece biter. Artık o programı naparsınız bilmem. Bence 15 gün sonra silin daha iyi. Son olarak, bu yazıyı benim gibi bu konuyu yeni öğrenenler için olabildiğince açık anlatmaya çalıştım. Eğer Mr.Stop bu yazıyı sitesinde yayınlarsa iki şeyi yapmaya çalıştım. Birincisi bu günlerde artık olmazsa olmaz hale gelen unpack olayı ve bunun için gereken araçların kullanımını ve deneyimlerimi paylaşmak. İkincisi, çok zor gibi görünen korumaların bile bilgi paylaşımı ile kolay hale dönüşebileceğini göstermek.

Bu yazının bir çok noktası aslında bir çok noktada diğer paketlenmiş dosyalar için de uygun :) Şahsen bu bilgilerin neredeyse tıpkısını kullanarak, başka AsProtect, AsPack gibi programlarla korunmuş 2-3 programı daha bir çırpıda hallettim desem hiç mi hiç yalan olmaz. Heh he. Deneyin görün. Tabi bir sürü istisnası da var. Bilgi Paylaşmak İçindir. Kolay Gelsin. Mr. Stop a tekrar teşekkürler.

Son Notlar

Bir programı kullanarak para kazanıyorsanız, programı satın alın.