Skip to content

Latest commit

 

History

History
391 lines (300 loc) · 11.1 KB

asm.md

File metadata and controls

391 lines (300 loc) · 11.1 KB

+

portable executable (PE)

main

CALL  _get_initial_narrow_environment
MOV   EDI,EAX
CALL  __p___argv                     
MOV   ESI,dword ptr [EAX]
CALL  __p___argc                     
PUSH  EDI
PUSH  ESI
PUSH  dword ptr [EAX]
CALL  FUN_00402100                   

executable and linkable format (ELF)

symbols

# Imports
objdump --dynamic-syms

# Externally visible / Exports
# ELF format
# Given: Symbol table '.dynsym'
nm --demangle --dynamic --defined-only --extern-only _
readelf -Ws _ | awk '{ if (!match("0000000000000000", $2)) print }'
# PE Format
winedump -j export foo.dll
mingw-objdump -p foo.dll

section headers

# sections + binary position
objdump -h
readelf --sections
~/opt/pax-utils/dumpelf

# dump a section
objcopy --dump-section .text=output.bin input.o
Sections Lifecycle
argc,argv,envp
stack grows to bottom (lower addresses)
heap grows to top (higher addresses)
uninitialized data aka. .bss zeroed by exec
initialized data aka. .data read by exec
initialized read-only data aka. .rodata read by exec
global offset table aka. .got updated by _dl_runtime_resolve, replacing pointer to stub in .plt
executable code aka. .text read by exec
procedure linkage table aka. .plt
  • .text: executable code; RX (=AX) segment; only loaded once, as contents will not change

  • .rela.text: list of relocations against .text

  • .data: initialised data; RW (=WA) segment

  • .rodata: initialised read-only data; R (=A) segment

  • .bss: uninitialized data; RW segment

  • .plt: PLT (Procedure Linkage Table) (IAT equivalent)

  • .got: GOT (Global Offset Table), used to access dynamically linked global variables, created during link time, may be populated during runtime

  • .got.plt: used to access dynamically linked functions

  • .symtab: global symbol table

  • .dynamic: Holds all needed information for dynamic linking

  • .dynsym: symbol tables dedicated to dynamically linked symbols

  • .strtab: string table of .symtab section

  • .dynstr: string table of .dynsym section

  • .interp: RTLD embedded string

  • .rel.dyn: global variable relocation table, used for ASLR

  • .rel.plt: function relocation table, used for ASLR

  • Technovelty - PLT and GOT - the key to code sharing and dynamic libraries

  • ELF Binaries and Relocation Entries - shorne in japan

  • c - Why this piece of code can get environment variable address? - Stack Overflow

golf, strip

https://www.sigflag.at/blog/2020/writeup-plaidctf2020-golfso/

call convention (e.g. registers for arguments, return values)

https://man7.org/linux/man-pages/man2/syscall.2.html

stack

  • frame
    • contains: ebp; local vars; args; return address = eip saved by call

self-modifying code

  • X86 Emulator Plugin
    • Every time an instruction is fetched, the plugin tells IDA to turn that location into code
    • ~/Downloads/BH_Eagle_ida_pro.pdf

https://stackoverflow.com/questions/27581279/make-text-segment-writable-elf https://stackoverflow.com/questions/54134394/segmentation-fault-with-a-variable-in-section-data https://stackoverflow.com/questions/4812869/how-to-write-self-modifying-code-in-x86-assembly https://0x00sec.org/t/polycrypt-experiments-on-self-modifying-programs/857 https://guyonbits.com/from-rodata-to-rwdata-introduction-to-memory-mapping-and-ld-scripts/ gdb p (int)mprotect($rax - $rax%4096, 4096, 7) without libc gdb # 10: __NR_mprotect set $rax = 10 set $rdi = addr set $rsi = len set $rdx = 3 jump syscall ? push/pop registers https://stackoverflow.com/questions/25740781/change-page-permission-using-gdb

code cave

https://red0xff.github.io/writeups/volgactf_fhash/#6acb76aa304fcff925cebfc5ac2534de

patterns

stack

; function init ~= `enter` instruction
push rbp
mov rbp,rsp
push rbx

; stack space for locals
sub rsp,0x18

; store argv[1]
mov rsi,qword [rsi + 0x8]

; [...]

; return value of next call
mov eax,0x0
; arguments of next call
mov rdi,0x1 
call fun_0123

; mem ptr can be stored as extra local var
LEA RAX,[DAT_00100973]
MOV qword ptr [RBP + local_10],RAX
; ...added with var for addressing at index
MOV    EAX,dword ptr [RBP + local_18]
MOVSXD RDX,EAX
MOV    RAX,qword ptr [RBP + local_10]
ADD    RAX,RDX

; [...]

; release stack space
add rsp,0x18

; function exit ~= `leave` instruction
pop rbx
pop rsp
ret
Frame $rbp Offset Value Address
+ argc,argv,envp [...]
1 + parameters [bgn]0x7fffffffffb0
1 + $rip [bgn]0x7fffffffffa8
1 + $rbp [end]0x7fffffffffa0
1 + [alignment] [end]0x7fffffffff94
1 + locals [end]0x7fffffffff30
2 + parameters [...]
2 + $rip [...]
2 0 $rbp [...]
2 - [alignment] [...]
2 - locals [...]
2 - $rsp [...]
  • $rbp aka. frame pointer
  • $rip aka. return address

registers

  • ah, - PRESERVES 0xffff00ff bits of eax, equivalent for rax
  • al, ax - PRESERVES {8,16} high bits of eax, equivalent for rax
  • eax - ZEROES 32 high bits of rax

https://stackoverflow.com/questions/25455447/x86-64-registers-rax-eax-ax-al-overwriting-full-register-contents/25456097

assembling

gcc -no-pie -nostdlib foo.s -o foo
# || 32 bits
gcc -m32 -no-pie -nostdlib foo.s -o foo

# || Using Intel syntax
nasm -f elf -o foo.o foo.asm
ld -m elf_i386 -o foo foo.o

# || Using AT&T syntax
as -o foo.o foo.asm
ld -o foo foo.o

http://asm.sourceforge.net/intro/hello.html https://cs.lmu.edu/~ray/notes/gasexamples/ https://stackoverflow.com/questions/36861903/assembling-32-bit-binaries-on-a-64-bit-system-gnu-toolchain

https://stackoverflow.com/questions/46756320/change-a-call-address-in-memory

dissassembling

objdump -d _.so | grep func
nm -A _so | grep func

dumpbin /exports _.dll | find "func"
# || CFF Explorer

c++filt -n _ZdlPvm
readelf -Ws _.so
objdump -TC _.so
nm -gC _.so

# From raw data
# Reference: https://www.synacktiv.com/posts/challenges/sharkyctf-ezdump-writeups-linux-forensics-introduction.html
objdump -b binary -m i386:x64-32:intel -D shellcode.bin

16-bit

ida -m 0x100 -b 16 foo.com

cross-architecture

# multiarch
sudo apt install \
    binutils-aarch64-linux-gnu \
    binutils-mips-linux-gnu \
    binutils-powerpc-linux-gnu \
    binutils-arm-linux-gnueabi \
    qemu-user \
    qemu-user-static

# arm
sudo apt install \
    qemu-system-arm \
qemu-arm -L /usr/arm-linux-gnueabihf/ crackme

https://github.com/OAlienO/CTF/tree/master/2018/HITCON-CTF/Baldis-RE-Basics https://padraignix.github.io/reverse-engineering/2020/05/18/nsec2020-crackme/

compiling

sudo apt install \
    gcc-arm-linux-gnueabi \
    gcc-arm-linux-gnueabihf \
    binutils-arm-linux-gnueabi \
    libc6-armel-cross \
    libc6-dev-armel-cross
arm-linux-gnueabi-gcc ~/code/wip/hello.c -o hello_arm_static -static

https://www.acmesystems.it/arm9_toolchain

attaching to debugger

qemu-arm -g 18080 _
gdb-multiarch _
# set arch mips
# set endian big
# target remote localhost:18080

https://padraignix.github.io/reverse-engineering/2020/05/18/nsec2020-crackme/

boot disk, MBR

qemu-system-x86_64 -s -S -m 512 -fda winxp.img

https://github.com/VoidHack/write-ups/tree/master/Square%20CTF%202017/reverse/floppy

toolchains

dynamic linking

https://in4k.github.io/wiki/lsc-wiki-rtld

position independent executable (PIE)

https://stackoverflow.com/questions/2463150/what-is-the-fpie-option-for-position-independent-executables-in-gcc-and-ld https://access.redhat.com/blogs/766093/posts/1975793

switching between 32-bit and 64-bit modes

endianess

uint32_t read_le_int32(unsigned char *b) {
    return uint32_t(b[0]) |
            (uint32_t(b[1]) << 8) |
            (uint32_t(b[2]) << 16) |
            (uint32_t(b[3]) << 24);
}

address translation

windows

  • virtual address (VA) = original virtual address of object loaded into memory
  • relative virtual address (RVA) = VA - ImageBase
    • e.g. 0x1000 = 0x401000 - 0x400000
  • file offset of entry point = (.OptionalHeaders[EntryPointAddress] – .SectionHeaders[VirtualAddress[.text]]) + .SectionHeaders[PointerToRawData[.text]]

linux