Offset mos kelmasligini tushunishga harakat qilaylik. "A" belgilaridan iborat katta padding buffer ning birinchi qismini ko‘rib chiqsak, u malloc funksiyasiga 780 hajmdagi chaqiruv bilan boshlanishini ko‘ramiz:

int initial_buffer_size = 780;
char *padding = malloc(initial_buffer_size);

Ro‘yxat 17 - malloc yordamida dastlabki buffer uchun xotira ajratish

Bu raqam tanish bo‘lishi kerak. Modulning boshida ta’kidlaganimizdek, 780 – bu stack da return address ni qayta yozish va EIP registrini boshqarish uchun zarur bo‘lgan offset baytlari soni.

malloc funksiyasi faqat so‘ralgan hajmga asoslangan xotira blokini ajratadi. Bu buffer to‘g‘ri initialize qilinishi kerak, bu malloc chaqiruvidan so‘ng darhol memset funksiyasi yordamida amalga oshiriladi:

memset(padding, 0x41, initial_buffer_size);

Ro‘yxat 18 - Dastlabki buffer ni "A" belgilar bilan to‘ldirish

memset yordamida xotira ajratmasi muayyan belgi bilan to‘ldiriladi, bizning holatda bu "0x41", ya’ni ASCII da "A" belgisining olti o‘nlik (hex) ko‘rinishi.

Exploit dagi keyingi kod qatori ayniqsa qiziqarli. Biz memset chaqiruvini topamiz, u ajratmaning oxirgi baytini NULL baytga o‘rnatadi:

memset(padding + initial_buffer_size - 1, 0x00, 1);

Ro‘yxat 19 - memset yordamida oxirgi baytni null-terminator ga o‘rnatib, buffer ni string ga aylantirish

Bu dastlab chalkash tuyulishi mumkin; ammo, kodni o‘qishni davom ettirsak, yakuniy buffer yaratiladigan qatorlarga yetamiz:

char *buffer = malloc(buffer_length);
memset(buffer, 0x00, buffer_length);
strcpy(buffer, request_one);
strcat(buffer, content_length_string);
strcat(buffer, request_two);
strcat(buffer, padding);
strcat(buffer, retn);
strcat(buffer, shellcode);
strcat(buffer, request_three);

Ro‘yxat 20 - Exploit uchun yakuniy buffer ni yaratish

Kod buffer belgi massivi uchun xotira blokini malloc yordamida ajratishdan boshlanadi, so‘ngra massivni NULL baytlar bilan to‘ldiradi. Keyin, kod buffer belgi massivini boshqa o‘zgaruvchilarning mazmunini strcpy va strcat kabi turli string manipulation funksiyalari orqali ko‘chirish orqali to‘ldiradi.

Yakuniy buffer string sifatida tuzilishi kerakligini bilish juda muhim. C dasturlash tili null-terminated strings dan foydalanadi, ya’ni strcpy va strcat kabi funksiyalar string ning oxiri va hajmini target belgi massivida birinchi NULL baytning paydo bo‘lishini qidirish orqali aniqlaydi. Dastlabki padding buffer ning ajratma hajmi 780 bo‘lganligi sababli, oxirgi baytni 0x00 ga o‘rnatish orqali biz 779 bayt uzunlikdagi "A" ASCII belgilar string ini concatenate (strcat) qilamiz. Bu EIP ning noto‘g‘ri hizalanib qayta yozilishini tushuntiradi.

Biz bu mos kelmaslikni initial_buffer_size o‘zgaruvchisi bilan belgilangan so‘ralgan xotira hajmini 1 ga oshirish orqali tezda tuzatishimiz mumkin:

int initial_buffer_size = 781;
char *padding = malloc(initial_buffer_size);
memset(padding, 0x41, initial_buffer_size);
memset(padding + initial_buffer_size - 1, 0x00, 1);

Ro‘yxat 21 - Padding ajratma hajmini o‘zgartirish

Yakuniy sinov sifatida, biz kodni yana compile qilamiz, reverse shell ni ushlash uchun 443 port da Netcat listener ni sozlaymiz va Sync Breeze xizmati target mashinada ishlayotganligiga ishonch hosil qilgandan so‘ng, exploit ni ishga tushiramiz: