Uploaded by Kate Chumachenko

firstprog c

advertisement
`gcc firstprog.c -o firstprog`
-g (include extra debugging information (gdb will have access to the source code))
`objdump -D firstprog | grep -A20 main.:` (show 20 lines after main.:) ![](Pasted%20image%2020230428005518.png)
-> examine compiled binaries (assembly AT&T syntax (cacophony of % and $))
`objdump -M intel -D firstprog | grep -A20 main.: ` (Intel syntax assembly)
A byte has 256 (2^8) possible values, so each byte can be described with 2 hexadecimal digits.
The 32-bit processors have 2^32 possible memory addresses, 64-bit processors have 2^64.
64-bit processors can run in 32-bit compatibility mode, which allows them to run 32-bit code quickly.
Register - are like internal variables for the processor. `gdb -q firstprog` (`echo "set disassembly intel" > ~./gdbinit` -> set Intel syntax)
![](Pasted%20image%2020230428011236.png)
-> show registers before executing the main() function
(EAX - Accumulator, ECX - Counter, EDX - Data, EBX - Base) - are general-purpose registers.
(ESP - Stack Pointer, EBP - Base Pointer, ESI - Source Index, EDI - Destination Index) - are
general-purpose registers but pointers and indexes. The ESP and EBP are called pointers because they store 32-bit addressed, which essentially point to that location in memory. These registers are fairly important to program execution and memory management; The ESI and EDI are also technically pointers, which are commonly used to point to the source and destination when date needs to be read from or written to.
(EIP - Instruction Pointer) - points to the current instruction the processor is reading. EFLAGS - consists of several bit flags that are used for comparisons and memory segmentations.
The assembly instructions in Intel syntax generally follow this style:
operation \<destionation\>, \<source\>
The destination and source will either be a register, a memory address or a value.
mov - move value from the source to the destination
![](Pasted%20image%2020230428013446.png)
The instructions will move the value from RSP to RBP and then subtract 10 from RSP.
cmp - compare values
jmp - jump jle - jump if less than or equal to
![](Pasted%20image%2020230428014438.png)
The instruction compares the 4-byte value located at RBP minus 4 with the number 9. The next instruction is referring to the result of the previous comparison. If the value is less than or equal to 9, execution will jump to 0x114a.
![](Pasted%20image%2020230428020934.png)
`info register rip` -> can be shortened to `i r rip`
Funciton prologue is instructions before the value of RIP register. It is generated by the compiler to set up memory for the rest of the main() funciton's local variables.
Examine memory - `x/<how to display that memory> <location in memory>`
The display formats:
o - Display in octal
x - Display in hexadecimal
u - Display in unsigned, standard base-10 decimal
t - Display in binary
i - Display in assembly instructions
c - Display in ascii characters
s - Display an entire string of character data
![](Pasted%20image%2020230428022016.png)![](Pasted%20image%2020230428022404.png)
`x/12x $rip` - examins 12 units of the RIP register.
The default size of a single unit is a four-byte unit called a word. The size of the display units for the examine command can be changed by adding a size letter to the end of the format letter.
The size letters:
b - A single byte
h - A halfword, which is 2 bites
w - A word, which is 4 bytes
g - A giant, which is 8 bytes![](Pasted%20image%2020230428023133.png)
On the x86 processor values are stored in little-endian byte order, which means the least significant byte is stored first.
![](Pasted%20image%2020230428024153.png)
`x/i $rip` - show examined memory in corresponding assembly instruction
![](Pasted%20image%2020230428025315.png)
This assembly instruction wil move the value of 0 into memory located in the PTR register, minus 4.
This is where the C variable `i` is stored in memory; `i` was declared as an integer that uses 4 bytes of memory on the x86 processor. The memory in this location(register) can be examined several different ways: ![](Pasted%20image%2020230428025846.png)
`nexti` - executes the next instruction. The processor wil read the instruction at RIP, execute it, and advance RIP to the next insturction.
![](Pasted%20image%2020230428030812.png)
cmp, jle, jmp -> creates an if-then-else control structure.
![](Pasted%20image%2020230428033306.png)
![](Pasted%20image%2020230428032215.png)
The bytes 0x48, 0x65, 0x6c, 0x6f all correspond to letters in the ASCII table.
These commands reveal that the data string `"Hello , world!\n"` is sotred at the RAX register.
lea - Load Effective Address.
0x263 or pointer.c
The EIP (instruction pointer) register is a pointer that "points" to the current instruction during a program's execution by containing its memory address. Pointers: instead of copying a large block of memory, it is much simpler to pass around the address of the beginning of that block of memory.
Memory on the x86 architecture uses 32-bit addressing, so pointers are also 32 bits in size (4 bytes). Instead of defining a variable of that type, a pointer is defined as something that points to data of that type.
To see the actual data stored in the pointer variable, use the address-of operator `&`(ampersand), so the address of that variable is returned, instead of the variable itself.
![](Pasted%20image%2020230430224414.png)
Located at the address `0x7fffffffe1c8`, and it contains the address `0x7fffffffe1a0`
To see the data found in the address the pointer is pointing to, use the dereference operator `*`(asterisk).
![](Pasted%20image%2020230430225332.png)
0x264 or fmt_strings.c
Format parameters or escape sequences in C:
%d - Decimal (allow negative values)
%u - Unsigned decimal (only positive values)
%x - Hexadecimal
%f - Float
%p - Memory address
%s - String
%c - Character
%n - Number of bytes written so far
(%p = %08x)
These formats expect to be given a memory address; it prints the data at that memory address untila a NULL byte is encountered. %n is unique and writes the number of bytes that have been written so far into that memory address. Two's complement - flips all the bits and adds one.
The scanf function waits for an address to input data to. `scanf("%format parameter", &destination address);`
0x265 or typecasting.c
Typecasting is a way to temporarily change a variable's data type. `(typecast_data_type) var`
The pointer's type determines the size of the data it points to.
![](Pasted%20image%2020230501004040.png)
The void pointer is really just holding the memory address, while the hard-coded typecasting is telling the compiler to use the proper types whenever the pointer is used. The void pointer is truly nothing more than a memory address and with the data types defined by typecasting, anything that is big enough to hold a four-byte value can work the same way as a void poiner. 0x266 or commandline.c
![](Pasted%20image%2020230501233931.png)
To save the number of arguments in arg_count and every argument in pointer to char array arg_list;
atoi(pointer to a string) - ASCII to integer
SEGMENTATION FAULT - a program dies trying to access and address that is out of bounds.
static var - you cannot change it once you gave it a value and it is only initialized once.
0x270
A compiled program's memory is divided into 5 segments: text,d ata, bss, heap, stack;
The text segment (code segment) - where the assembled machine language instructions of the program are located. + As a program executes, the EIP is set to the first instruction in the text segment. The processor then follows an execution loop that does:
1. Reads teh instructiono that EIP is pointing to 2. Adds the byte length of the instruction to EIP
3. Executes the instruction that was read in step 1
4. Goes back to step 1
Write permission is disabled in the text segment, as it is not used to store variables, only code. This prevents us from actually modifying the program code; any attemp to write to this segment of memory will cause an alert and the program will be killed.
This memory segment has a fixed size, since nothing ever changes in it.
+ The data and bss segments are used to store global and static program variables. The data segment is filled with the initialized global and static program variables, while the bss segment is filled with their uninitialized counterparts. These segments are writable, but have a fixed size. + The heap segment is used for programmer to directly control.
Blocks of memory in this segment can be allocated and used for whatever the programmer might needs. The heap segment isn't of fixed size, so it can grow larger or smaller as needed. The growth of the heap moves downward toward higher memory addresses.(dynamic)
+ The stack segment is used as a temporary scratch pad to store local function variables and context during function calls. This segmen isn't of fixed size.
The stack segment is used to remember all of the passed variables, the location the EIP should return to after the function is finished, and all the local variables used by the function. All of this information is stored together on the stack in what is called a stack frame. A stack contains many stack frames.
A stack has first-in, last-out (FILO) ordering, which means the first item that is put into a stack is the last item to come out of it. Pushing - an item is placed into a stack. Popping - an item is removed from a stack.
The ESP register is used to keep track of the addresses of the end of the stack, and because it is frequently changed, stack isn't of a fixed size.
As the stack changes in size, it grows upward in a visual listing of memory, toward lover memory addresses. The EBP (frame pointer, local base pointer) - is used to reference local function variables in the current stack frame. Each stack frame contains parameters to the funciton, its local variables, two pointers that are necessary to put things back the way they were: the saved frame pointer (SFP) and the return address. The SFP is used to store EBP to its previous value, and the return address is used to restore EIP to the next instruction found after the function call. This restores the functional context of the previous stack frame. 0x272
![](Pasted%20image%2020230825081047.png)
If a big block of memory is allocated and then deallocated, the final 15-byte allocation will occur in that freed memory space. On my system it happens on 1033rd byte.
0x281 *File Access* or simplenote.c
Common functions that use file descriptors are:
- open() - opens a file for reading and/or writing and returns a file descriptor. The arguments are a pointer to the filename to open and a series of predefined flags that specify the access mode. Include fcntl.h and sys/stat.h to use these flags:![](Pasted%20image%2020230826093319.png)
The returned file descriptor is just an integer value, but it is unique among open files. It is passed as an argument to the other functions like a pointer to the opened file.
- close() - file descriptor is the only argument.
- read() - the arguments are the file descriptor, a pointer to the data to read, and the number of bytes to read.
- write() - the arguments are the file descriptor, a pointer to the data to write, and the number of bytes to read.
All of these functions will return -1 if there is an error.
0x283 Permissions
setuid (set user id) flag - The program will run as the owner user when any user runs this program. chmod u+s file.c
0x300 Exploitation
./overflow_example $(perl -e 'print "A"x300') - quick test gcc flag to compile for 32-bit: -m32
NOP sled - Shellcode - Repeated return address
NOP (no operation) byte in x86 is 0x90.
https://mcsi-library.readthedocs.io/articles/2022/06/linux-exploitation-x64-shellcode/linux-exploitation-x64-shellcode.html
Download