###### tags: `module11` `revers` `programming language` `assembler`
[ToC]
# Занятие 3. Ассемблер. Структура разработки, инструкции, регистры.
## Видеозапись урока
{%youtube zng8LSTzwDE %}
### timecodes
00:00:00 Ждем
00:02:25 что было и что будет
00:09:10 Создание исполняемого файла
00:15:40 Граф потока управления
00:19:55 Регистры процессора x86
00:36:10 Флаги процессора
00:41:25 Регистры процессора x64
00:44:00 Перерыв
00:50:15 Операции с данными.
01:00:55 Обращение к памяти
01:07:17 Логические инструкции
01:10:00 Сдвиги бит
01:13:20 Инструкции контроля управления
01:25:18 Инструкции работы со строками
01:30:26 Общие инструкции
01:36:00 Перерыв
01:47:50 Различие синтаксисов Intel / AT&T
01:50:00 Стек
01:51:53 Соглашения о вызовах
02:09:00 NASM
02:12:30 Получение информации о процессе
02:15:40 Практика. Смотрим код crackme.
02:24:40 Пробуем разобраться с проблемами
02:32:30 Дебажим crackme
02:36:45 Немного о следующем занятии
02:39:30 Смотрим код import_by_hash.cpp
02:02:30 Дебажим import_by_hash
02:15:40 Заключение
## Концепт обратной разработки
## Создание исполняемого файла

импорт - экспорт на этапе линкования
лоадер выделяет все необходимые ресурсы и загружают библиотеки и передает управление на точку входа приложения
задача из исходных кодов понять всю лгику работы приложения
### Граф потока управления
+ Порядок инструкций, которые будут исполнены
+ Поток исполняет инструкции последовательно, пока не встретит инструкцию ветвления
+ Блоки кода – логически сгруппированные инструкции

## Примитивы ассемблера
большинство малвари создано под архитектуру x86, так как гарантированно будет работать и на 64-bit
### Регистры процессора x86
имена регистров это аббревиатура и у них есть расшифровка.
+ Общего назначения
+ EAX - сложение и умножение **(может вычитание)**;в винде часто может содержать результута возврата функции. ?особое внимание?
+ EBX - позволяет раотать с масивами, структурах, перечеслениях. выступает как индекс
+ ECX - счетчик для ?"циклов"?
+ EDX - деление и **умножение опять** остаток от деления
+
+ работает со стеком.
+ EBP - разделяет локальные переменные и аргументы функции (локальные переменный <-EBP+> аргументы функции)
+ ESP - указывает вершина стека и постоянно меняется
+ работа с памятью и строками, например для сравнения данных EDI с ESI; заполнения нулями данных положенных в EDI
+ ESI Source
+ EDI Distination
+ Специальные
+ EIP - указывает на выполяемую инструкцию, может быть изменен для принудительного переключения на нужную иструкцию
+ EFLAGS
+ Сегментные:
+ CS - адрес на сегмент кода
+ DS - адресс на сегмент данных
+ ES
+ FS - используется в винде, содержит много стуктур процесса
+ GS
+ SS - стэк
EAX, EBX, ECX, EDX могут быть представлены как dword, word и byte
На примере EAX
• EAX – dword
• AX – младший word в EAX
• AH – старший byte в AX
• AL – младший byte в AX
EBP, ESP, ESI, EDI могут быть только dword и word
На примере EBP
• EBP – dword
• BP – младший word в EBP

#### EFLAGS
• CF(care flag) – флаг переноса
• PF(parity адфп) – флаг чётности если крайний бит равен 1, то число нечетное
• ZF(zero flag) – флаг нуля
• SF(signed flag) – флаг знака если старший бит равен 1 то число отрицательное
• DF(direction) – флаг направления, указывает направление обработки, например ESI и EDI
• OF(overflow) – флаг переполнения
в чем разница между CF & OF?
### Регистры процессора x64
• Общего назначения - теже самые как и в x86 но уже в 64Bit
+ RAX, RBX, RCX, RDX, RBP, RSP, RSI, RDI - бьются на EAX,AX т.е до 16bit
+ R8-R15 (R8D, R8W, R8B) - деляться до 8bit
• Специальные
• RIP
• RFLAGS
паремтры функци передаются церез регистры процессора, а не через стек, а то что не влезло уже через стек. эти достигется ускорение, так как не надо обращаться к памяти.
### Арифметические операции
• ADD / SUB модем работать как с регистрами так и с памятью
• (I)MUL / (I)DIV умножение и деление
• INC / DEC инкремент/декримент. например, для циклов
• NEG получение двоичного числа, кторое в суммме с текущим даст нам 0
• CMP сравнение двух значений. результат которой меняет регистры, кторые потом могут быть провереныю
### Перемещения данных
• MOV - помещает значение в память
• CMOVcc - заполняет масив какимито данными. сс - тип байт, ворд
• XCHG - поменяет ячейки местами
• MOVSc/MOVZx - используя esi/edi происходит заполнение данными где x/c -B W DW
• PUSH / POP поместить в стек/ забрать из стека
• PUSHA / PUSHAD поместить в стек все значения текущих регистров/
• POPA / POPAD забрать из стека все значения текущих регистров/
• PUSHF / PUSHFD поместить в стек все значения текущих флагов
• POPF / POPFD забрать из стека все значения текущих флагов
### Обращение к памяти
Задание числом: `mov eax, 0x3418`
Задание регистром: `mov eax, ebx`
Задание переменной: `mov eax, dword_412420`
Задание с помощью сегменты: `mov eax, [DS:41242]`
если мы поместим адрес [] , то мы прочитаем знаечение по этому адресу.
Например:
[EAX] – доступ к выделенной памяти
[EBP + 0x20] – доступ к переменной на стеке
[EAX + EBX * 8] – массив с 8-байтными структурами
[EAX + EBX + 0xC] – доступ к полю в структуры в массиве структур
### Логические инструкции
• AND
• OR
• XOR часто используемая для шифрования инструкция. легко обратимо обратно
• NOT

https://inf1.info/bitwise-operations
### Сдвиги бит
• SHL / SHR арифметический сдвиг влево/вправо (* и / на 2) новые биты заполняются нулями
• SAL / SAR арифметический сдвиг влево/вправо (* и / на 2) новые биты заполняются нулями
• ROL / ROR циклический сдвиг влево/вправо биты не теряются а переходят по кругу в переменной. тоже часот может быть применнено для запутывания, так как легко обратима обратна.
### Инструкции контроля управления
• JMP безусловный переход по указанному адресу
• TEST похоже на cmd, только выполянет логическое сравнеие AND. так же как cmd предворяет иструкции переходя
• Jcc переход по указанному адресу в зависимости от значений флага(cc) сс=z/s/....
• LOOP - встречать будем редко, простой цикл. счетчик - ECX
• CALL - вызов процедуры(передача управления по указанному адресу)
• RET - завершение функции, прочитать адрес возврата со стека и вернуться в место откуда были вызваны.
• INT - вызывает обработчик прерываний, INT3 или 0xCC в 16ном виде - будем встречать часто. Вызывает передачу отладчику. Анлог brakepoint'a. злоумыщленники могут следатть за этим же прерыванием, что бы определить что их зловред отлаживают или наоборот испольщзовать, что бы запутать аналитика. В прилождениях отладки этот брэйкпоинт могут заменять на кастомный.
### Инструкции работы со строками
c=b/w/dw
• MOVSc копирует данные из ESI в EDI
• CMPSc сравнивает данные согласно указанного счетчика и направления в памяти
• SCASc сравнивает **?регистры?**
• STOSc сохраняет в память содержимое в EAX. для быстрой инициализации строк и др данных. опять же учитывается направление
• LODSc считывает из памяти в регистр. обраное STOSc
• REP повтор иструкции заданное в регистре раз
### Общие инстукции
• LEA - почти как mov, но с некоторыми отличиями. mov больше для работы с регистрами, lea больше для работы с памятью
• NOP - пустая операция
• UD2 - неопределенная операция. тоже позволяет выполянть точку остановки
• CPUID - позволяет идетентифицировать текущий процессор.
## Синтаксис
### Intel / AT&T
```a
Intel AT&T
mov eax,[ecx] movl (%ecx),%eax
mov ax,[bx+3] movw 3(%bx),%ax
mov eax,[ebx+20h] movl 0x20(%ebx),%eax
add eax,[ebx+ecx*2h] addl (%ebx,%ecx,0x2),%eax
lea eax,[ebx+ecx] leal (%ebx,%ecx),%eax
sub eax,[ebx+ecx*4h-20h] subl -0x20(%ebx,%ecx,0x4),%eax
jmp large fword ptr ds:[666h] ljmp *0x666
pop ax popw %ax
```
### Стек

## Соглашения о вызовах
### Пролог функции

cdecl

после вызова фунции необходимо вернуть стек в исходное состояние
stdcall / winapi

функция сама выполняет очистку стека
fastcall

для ускорения вызова, некотрые параметры помещаютмся в регисрт, а не в стек
thiscall
при вызове \этой функции в ECX кладется адрес вызываемого класса.
## NASM


## Получение информации о процессе
TIB/TEB/PEB
TIB (FS) – блок информации о текущем рабочем потоке, существует для каждого процесса
• FS:[0x00] - Structured Exception Handling - используют злоумышленики
• FS:[0x18] - Адрес TEB
• FS:[0x30] - Адрес PEB, можно нати все что замапленно процессом в память. тоже очень любят злоумышленники
## Практика
2:37:20 злоумышленник всегда будет использовать строки, но скорее всего будет их шифровать
ловим функции loadlibrary getprocaddress . ищмем все строки котрые ссылються в эти функции и дальше возможно определяем наши функции и востанавливаем их.
### import_by_hash.cpp использует PEB
только под x86
```c=
#define STDCALL __stdcall
#define VK_ESCAPE 27
typedef unsigned long DWORD;
#include "stdio.h"
#include "string.h"
// Define some function pointers for 1,2, ...5 args
typedef DWORD(STDCALL* funcPtr0)(void);
typedef DWORD(STDCALL* funcPtr1)(DWORD);
typedef DWORD(STDCALL* funcPtr2)(DWORD, DWORD);
typedef DWORD(STDCALL* funcPtr3)(DWORD, DWORD, DWORD);
typedef DWORD(STDCALL* funcPtr4)(DWORD, DWORD, DWORD, DWORD);
typedef DWORD(STDCALL* funcPtr5)(DWORD, DWORD, DWORD, DWORD, DWORD);
// Here the function name hashes go
unsigned int hashTable[] = {
0xE9826FC6, // LoadLibraryA
0x38A66AE8, // ExitProcess
0xDE59F860, // GetAsyncKeyState
// add your hashes here
0 // zero terminate (cheaper than storing size)
};
// add your functions here in the order the hashtable has here
#define LoadLibraryA ((funcPtr1)functionTable[0])
#define ExitProcess (functionTable[1])
#define GetAsyncKeyState ((funcPtr1)functionTable[2])
void ResolveHashes(unsigned long module, funcPtr0* functionTable)
{
int i = (unsigned char)((i ^ i) - 1);
long tmp = *(long*)(*(long*)(module + 0x3C) + module + 0x78) + module;
int numImp = *(long*)(tmp + 0x18); // number of imports
while (--numImp >= 0)
{
// resolve import #numImp
unsigned char* importName = (unsigned char*)(*(long*)(*(long*)(tmp + 0x20) + module + numImp * 4) + module);
// now hash the import name and check it against a stored hash value
// code taken from [http://www.20to4.net/dat/importbyhash_v3.cpp](http://www.20to4.net/dat/importbyhash_v3.cpp "http://www.20to4.net/dat/importbyhash v3.cpp")
// so dont blame me for this asm passage, use your own hashing if you want to :)
// I however, was too lazy to use another hashfunc and recalc all my hashes...
unsigned int hash;
__asm
{
pushad
mov esi, importName
xor ebx, ebx
lodsb
calcloop :
xor bl, al
rol ebx, 6
lodsb
test al, al
jnz calcloop
mov hash, ebx
popad
}
//if (!strcmp((char const*)importName, "CreateFileA"))
//{
// printf("CreateFileA 'hash'");
//}
// now lookup hash
int j = (unsigned char)((j ^ j));
while (hashTable[j])
{
if (hash == hashTable[j])
{
// found the hash now resolve function entry
#define IMPORT_INDEX *(unsigned short*) (*(long*)((tmp + 0x24)) + module + numImp * 2)
functionTable[j] = (funcPtr0)(*(long*)(*(long*)(tmp + 0x1C) + module + 4 * IMPORT_INDEX) + module);
}
j++;
}
}
}
// this is important! dont let the compiler optimize stackframes
// for the main because we _WANT_ ebp addressing (smaller!!!)
#pragma optimize("y",off)
// need stdcall here to generate appropriate stackframe
int main()
{
// use locally (ebp indexed) function table
funcPtr0 functionTable[30]; // here your actual functions are stored
// note that there is a maximum of about 30
// if you use more only around 30 get translated
// to small calls, while you pay alot to the rest!
unsigned int module; // temporarily needed for calculating kernel32
// please forgive me this, but its really absolutly necessary
// if we want to detect kernel32 via PEB
// other methods like topstack could might hacked via plain c code
// however those methods arent as small and not guaranted to run!
// topstack especially does not run on XP64!
__asm
{
mov eax, DWORD ptr fs : [30h]
mov module, eax
}
// to check out why this works, search for "using PEB for retrieving kernel32"
module = *(long*)(*(long*)(*(long*)(*(long*)(module + 0x0C) + 0x1C)) + 0x8);
// resolve everything from kernel32
ResolveHashes(module, functionTable);
// and now since we have LoadLibraryA everything from other dlls...
ResolveHashes(LoadLibraryA((DWORD)"user32"), functionTable);
// ... load opengl32 etc ...
// your initcode goes here
do
{
// your rendercode goes here
} while (!GetAsyncKeyState(VK_ESCAPE));
return 0;
}
```
---
http://i-assembler.ru/25/Text/Command.htm
https://faydoc.tripod.com/cpu/stosb.htm