Частина 31 - x64 Збірка [Part 5]

Для повного змісту змісту всіх уроків, будь ласка, натисніть нижче, оскільки це надасть вам короткий зміст кожного уроку, а також теми, які будуть розглянуті. https://github.com/mytechnotalent/Reverse-Engineering-Tutorial

Ця лекція буде трохи довшою, ніж більшість, але важливо, щоб ви всі витратили час на справжнє кодування та практику тем, які будуть розглянуті нижче. Давайте переглянемо свій код:

Давайте скомпілюємо та запустимо:

Як ми бачимо з останньої лекції, ми успішно створили свій простий "Привіт, світ" програму. У попередніх лекціях я торкався x64 реєстрів, але я знову розгляну їх з цієї таблицею:

У попередніх лекціях ми описували, що ці реєстри складаються з основної функціональності, але важливо зрозуміти, що 64-бітові сегменти реєстрів складаються з 8-бітових сегментів. Реєстри містять тимчасову пам'ять. Це ключовий висновок тут. У нас є три секції в Linux-асемблері, які складаються з:

.data = складається з визначення даних

.bss = складається з розподілу змінних даних

.text = справжній код

У нашому прикладі вище ми використовували метку text, щоб не плутати її з .text секцією. Наш компілятор замінять кожну метку на справжнє розташування пам'яті в справжньому бінарному file. Важливо зрозуміти, що кожен символ рядка має довжину байта, яка представляється двома шістнадцятковими цифрами. Є таблиця ASCII, яку ви можете знайти в інтернеті, яка показує всі ці значення. Кожна шістнадцяткова цифра має довжину ніббла або 4 біта. Наприклад, наш 'H' є 0x48, а 'e' є 0x65. Давайте розглянемо наш бінарний файл в редакторі HEX, щоб проілюструвати. <div class="slate-resizable-image-embed slate-image-embedresize-full-width"></div>

У коментарях до останньої лекції Аарон вказав щось дуже критичне, чого слід розуміти, коли дивитися на Асемблер в операційній системі проти Firmware, наприклад, код, який ми створили для нашої операційної системи в попередніх лекціях. Аарон уважно вказав у коментарях останньої лекції, що SYSCALL повністю залежить від операційної системи. Системні виклики відрізняються залежно від операційної системи, оскільки кожна операційна система має свій власний ядро і свій власний вектор інтервалу таблиці, який має ідентифікатор, пов'язаний з відповідним числовим значенням. SYSCALL нічого більше, ніж коли бінарний файл запитує послугу від відповідного ядра, яке приймає аргументи або список вхідних даних. Важливо зрозуміти, що системи x64 аргументи або вхідні дані відповідають певним реєстрів:

Є 328 SYSCALLS в традиційному ядрі Linux. Як ми бачимо вище в нашому коді, ми використовуємо як SYS_WRITE, так і SYS_EXIT__.. Давайте проілюструємо:

Будь ласка, візьміть трохи часу, щоб переглянути наш код вище, щоб побачити, як це працює. У нас відбувається завантаження 1 у RAX, який є нашим SYSCALL. У нас відбувається завантаження 1 у RDI, який є нашим першим аргументом, який представляє наш стандартний вивід (0 = стандартний вхід та 2 = стандартна помилка). Наш другий аргумент завантажується у RSI, який є нашим text-етикетом, який при компіляції отримає справжню адресу пам'яті, яку ви побачите у дебагері. Нарешті, наш третій аргумент буде зберігати довжину рядка, яка становить 13 у нашому випадку, завантажену у RDX. Як завдання я хочу, щоб ви написали, як SYS_EXIT виконує те саме і пам'ятайте, що там є лише один аргумент. ПЛЮС ДОБРЕ ОСМІНИТИ код вище, щоб добре зрозуміти це, перш ніж продовжувати! Крім того, у нас є наш _start етикет, до якого наше відповідальне операційне середовище буде шукати, інакше воно буде викинути помилку, коли спробує знайти вхідний пункт нашого коду. Декларація global казує лінкеру справжню адресу даних. Наступна неділя ми відлагодимо байнів у GDB.

results matching ""

    No results matching ""