DLL, Ansi dan Unicode ga

DLL, Ansi dan Unicode ga

U2B3K

Bir dastur bor, hisobotlarni generatsiya qiladigan va ko'rsatadigan qismi bir kutubxonada qilingandi. Kutubxona eskiligi sababli Unicode belgilarni qo'llab-quvvatlamaydi. O'zbekcha harflar va boshqa unicode belgilar “?” qilib ko'rsatiladi. Shuni tuzatish kerak bo'lib qoldi. Dasturda hisobotlar qismini boshqa kutubxonadan foydalanib qilish ko'p vaqt oladi. Shunda shunchaki qiziqishga kutubxonani o'zini Unicode ni tushunadigan qilish mumkinmasmikin degan fikr kelib qoldi.

Darrov kutubxonaning dll faylini importlar jadvalini qaradim. Chunki ekranga yoki printerga chizish uchun Windows ning o'zining bazaviy kutubxonalaridagi grafik funksiyalardan foydalanishi aniqroq va shunday bo'lsa bu katta ehtimol GDI32.DLL yoki GDIPLUS.DLL lardan biridagi funksiyalar bo'ladi. Kutilganidek faylning importlar jadvalida matn chizish funksiyalaridan TextOutA va DrawTextA funksiyalari bor ekan (GDI32.DLL dan).

[Odatda Windows ning bazaviy kutubxonalari (Windows API) da matnli argumentlari bor funksiyalarning har biri ikkitadan bo'ladi. Biri Ansi belgi matnlar uchun, ikkinchisi Unicode tipidagi belgili matnlar uchun. Masalan yuqoridagi TextOut funksiyasi berilgan matnni ko'rsatilgan nuqtada chizish funksiyasi bo'lib, bu funksiya ikkita. Bittasi TextOutA - Ansi versiyasi, TextOutW - (Wide) Unicode versiyasi. Shuningdek DrawTextA va DrawTextW ham bor. Ansi matnlarda bitta belgi uchun 1 bayt ajratilsa, Unicode belgilar uchun kodirovkaga qarab 1, 2 yoki undan ko'p belgi ajratilishi mumkin.]

Demak bizga kerakli kutubxonamizda matnlarni chizishda TextOutA va DrawTextA lardan biri yoki ikkovisi ham ishlatilgan ekan. Nazariy jihatdan kutubxona ichidagi shu ikki funksiyani TextOutW va DrawTextW versiyalariga almashtirib qo'yilsa va kutubxonani ishlatayotganimizda dasturimizda matnlarni Unicode ga o'tkazib keyin kutubxonaga uzatsak muammo hal. Albatta amalda esa biroz boshqacharoq bo'ladi. 

Kutubxonani debuggerda ochib, hisobotlar ekranga (yoki printerga) chiziladigan joyini topdim (TextOutA va DrawTextA larga breakpoint qo'yish orqali).  Yaxshiki faqat bitta umumiy joy bor ekan, matnlarni chizish uchun kutubxonaning barcha chizish funksiyalari shu bitta funksiyani chaqiryapti va unda faqat TextOutA ishlatilyapti ekan.

Endi Gdi32.dll dagi TextOutW ni kutubxonaga, dll faylga import qilish kerak. Buning uchun PENet kutubxonasidan foydalanib qo'yaqoldim (PE fayllar bilan ishlash uchun qulay ekan).

OllyDbg da kutubxonaning chizish funksiyasiga o'tib, TextOutA ni chaqiriladigan qismini TextOutW ni chaqirishga almashtirib qo'ydim.

O'zgartirishlarni saqlab, kutubxonani tekshirib ko'rdim. Endi ekranga Unicode belgilar so'roq belgisisiz to'g'ri chiqdi, biroq ba'zida matn to'lig'icha chiqmay yoki ba'zida matndan keyin turli ierogliflar ham qo'shilgan holda chiqdi. Bu tabiiy. Chunki Ansi va Unicode belgili matnlarning uzunligi turlicha bo'ladi, chunki TextOutW funksiyasiga matn berilganda uning uzunligi ham beriladi, shunday parametri bor. Buning uchun TextOutW ni chaqirishdan oldin kutubxona kodida matnning uzunligini ham hisoblash bo'lishi kerak va u berilgan matnni Ansi matn deb o'ylab hisoblagan deb o'yladim.  Teparoqda WideCharToMultiByte funksiyasi orqali matnning uzunligi aniqlanib, keyin huddi shu funksiya bilan konvertatsiya qilinyapti ekan. Berilgan matnlar null terminated (matn oxiri null (yoki 0) kodli belgi bilan aniqlanadi, tugaydi). Mana shu yerda matn uzunligi noto’g’ri hisoblanyapti ekan. Uni to’g’rilash uchun biroz o’zgartirishlar kiritishga to’g’ri keldi, ya’ni kod orasiga qo’shimcha boshqa kod kiritish kerak bo’ldi. Buning uchun yana PENet kutubxonasi orqali dll faylga yangi bajariluvchi attributli seksiya qo’shdim. Chunki kodni orasiga shundayicha boshqa kodlarni yozib ketishning iloji yo’q, addresslar o’zgarib ketadi.

Buning uchun quyidagicha yo’l tutiladi. Aytaylik kodda quyidagi ketma-ketlik mavjud:

Address1:          Buyruq1

+1:                       Buyruq2

+2:                       Buyruq3

+3:                       Buyruq4

 

Shunda Buyruq2 va Buyruq3 orasiga qo’shimcha buyruq qo’shmoqchimiz. Hammasini shu to’rt buyruq joylashgan joyga (Address1 dan Address1+3 gacha) sig’ishi kerak. Bu notepadda ikki qator orasiga Enter ni bosib yangi qator yozib ketishdek emas albatta. Buyerda addresslar tushunish uchun +1, +2, +3 qilib olingan, aslida turli instruksiya uzunligi turlicha bo’lishi mumkin.

Address1:          Buyruq1

+1:                       Buyruq2

+2:                       Address2 ga o’tish buyrug’I (yoki Goto)

+3:                       Buyruq4

…

Address2:          Buyruq3

+1:                        Qo’shimcha buyruq1

+2:                        Qo’shimcha buyruq2

+n:                        Address1+3 ga o’tish buyrug’i

 

Buyerda Address2 – biz o’zimiz dll ga qo’shgan yangi kod seksiyasi manzili, uyerda dll ga tegishli hech narsa yo’q, chunki uni biz yangi qo’shdik. Natijada Address1 da Address1+3 ga manzilda ham Buyruq1, Buyruq2, Buyruq3, Buyruq4 lar bajarildi va qo’shimcha buyruqlarimiz ham bajarildi.

Kutubxonaga qaytamiz. O’zgartirgunimcha kod quyidagicha edi:

O’zgartirilgandan keyin:

Ya’ni 100290E7 manzilga JMP (shartsiz o’tish instruksiyasi) qo’shdim. U man yangi qo’shgan seksiyadagi man yozgan funksiyaga o’tadi, 10079070 manzildagi. Ya’ni WideCharToMultiByte ham chaqirilaveradi, lekin uning natijasi emas mening funksiyamning natijasi ishlatiladi kod davomida. Matn uzunligini o’zim hisoblab beraman. Bulardan keyin kod berilgan uzunlikda xotiradan joy ajratib, uni yana WideCharToMultiByte bilan Wide ko’rinishdan multibyte shaklga o’tkazadi. Ba’zi tafsilotlarni tashlab o’taman. DLL dagi o’zgarishlarni saqlab tekshirib ko’rdim. Yana to’g’ri natija yo’q, Unicode belgilar chizilyapti, biroq matn to’lig’cha emas yoki boshqa ieroglif belgilar qo’shilib qolyapti. Yana biroz pastroqqa tushib TextOutW ga matn butunicha emas, sikl Ichida belgilab berilayotganini topdim. Matndagi keying belgini o’qish yana user32.dll dagi CharNextA funksiyasi bilan bajarilyapti ekan. Bu ham ushbu funksiyaning Ansi versiyasi. DLL ga CharNextW ni import qilib, sikldagi CharNextA ni CharNextW ga almashtirdim. O’zgarishlarni saqlab yana tekshirib ko’rdim. Endi hammasi ko’ngildagidek ishladi.

Kutubxonaning yana bir funksiyasida alohida matnni chizish funksiyasi bor ekan, unga tegib o’tirmadim dasturimda ishlatilmagani uchun. Albatta yana qaysidir joylarida biror noto’g’ri joy qolib ketib qolgan bo’lishi mumkin. Lekin ancha tekshirib ko’rdim, binoyidek ishladi. Ishimni bitirish uchun bu to’g’ri variant ham emasdi. Shunchaki qiziqib qildim xolos.

Aslida bunaqa ishlarda mutaxassis ham emasman, biroz boshlang'ich tushunchalar va qiziqishim bor xolos. Lekin faraz qiling tizimlarni arxitekturalari, tuzilishlarini quyi darajalarigacha o’ta yaxshi tushunsangiz qancha imkoniyatlarga ega bo’lasiz?


Report Page