
For those of you that do not have a Linux operating system or the proper architecture, we go through all the steps of Virtual Machine installation and emulator installation, respectively. Also, we set up the system such that you will have all the tools that will be necessary during the time you will be taking this course (and after ;)
We discuss the different types of memory, how the memory caching mechanism works, CPU components, how the CPU works (with a specific example), ISA, what is the difference between RISC and CISC and the historical context
We discuss number bases, converting from binary to hexadecimal and vice-versa, data types in C/C++, and 2's complement method of signed numbers representation
We define what variables are, the reference (&) and dereference (*) operators in C/C++, we go through the Operating Systems concept of Virtual Memory, pointers and function pointers and the concept of endianness (Big-Endian vs Little-Endian)
Starting with a C program, we go through each building step, we learn about preprocessing directives, about compilation, assembly, static linking vs dynamic linking, how to build a static library and a shared library and the use of the ldd command
Again, starting with a C program, we look at every type of variable, how they are allocated and where each one of them will be stored at runtime, we learn the differences at the higher level between the stack, the heap and the static data sections, user space vs kernel space and finally, we learn about the /proc/[PID] directory in Linux and see how the memory allocations in C are mapped to the assembly code, by disassembling the executable with objdump
We learn about the general purpose registers, the Instruction Pointer, EFLAGS and the most basic use of registers in assembly. In the end, we write and build our very first assembly program.
We continue writing assembly by learning how to declare static memory in an assembly program, in parallel with a C program. In this context, we try to clarify the difference between C arrays and regular pointers and learn about memory addressing in assembly.
We start exploring with vanilla GDB a segmentation fault, we go through all the basic GDB commands and identify the source of the problem. Using the GDB Peda extension, we visualize in real time the state of the registers and the stack and learn something interesting about compilers, which is also the root cause for the crash.
We do a deep dive into instructions: ADD, SUB, INC, DEC, AND, OR, XOR, NOT, SHL, SHR, SAL and SAR
We do a deep dive into instructions: MOV, MOVZX, MOVSX, XCHG and LEA
We understand how the conditional (J**) and unconditional jumps (JMP) work and about the role of EFLAGS (especially Overflow Flag and Carry Flag) and CMP instruction in implementing conditionals. We also understand how more complex C/C++ expressions (such as if, while and for loops) can be implemented in assembly.
We put together most of what we learned in the previous 3 lectures to implement a more complex assembly program.
We learn all about allocating and de-allocating memory on the stack, the PUSH and POP instructions, and the ESP register.
Starting from a C program, we analyze the mechanism of function calling, go through the steps that an assembly function caller must do and through the steps of implementing a function in assembly. All these while following the state of the stack.
This course presents in a simple manner the assembly language - intel syntax - for the x86 32-bits architecture and places this in the context of a computing system. We start with a short presentation of the hardware components on which assembly code is highly reliant, how they work and what is their purpose in relation to the software. We continue with some higher level notions - data, variables, pointers, functions - as we understand them in languages such as C/C++ and we show all the steps that lead to the assembly language. By using a lot of demos and animations, we go through all the assembly language notions - registers, static memory, the stack, function calling, instructions - side by side with the more familiar concepts in higher level languages. In this process, we make use of multiple tools, both for static and dynamic analysis of binaries: GDB, objdump, nm. Towards the end, we touch on the security side of assembly. We do a deep dive into one of the most common vulnerabilities, buffer overflow and show how programs can be exploited. While on this topic, we present a binary analysis tool that is the bleeding edge in the domain of security: Ghidra.
This course is for people of any level and is the direct result of a desire to explain the concepts that were most useful to my career path in the simplest manner.