Particularly, in modern Linux binaries, syscalls are not hardcoded as int instructions, but are dynamically mapped via a "virtual DSO" mechanism to the best instruction for the current architecture (int 80, or syscall/sysenter).
Also, in practice, the ELF would be dynamically linking to libc, and libc would be making the calls.
"This is the whole file, however, most ELF files contain many more elements. Explanations are simplified, for conciseness."
Otherwise this I'd quite good. Helps people make the connection between Hello World in rodata and how it gets used
sample C code where you would expect to see int 0x80: #include <stdio.h>
void main(int argc, char argv) { char name[2]; name[0] = "/bin/sh"; name[1] = NULL; execve(name[0], name, NULL); exit(0);
}
when you build it and then use objdump -D: the relevant code is as follows: 8048419: 8d 54 24 18 lea 0x18(%esp),%edx 804841d: 89 54 24 04 mov %edx,0x4(%esp) 8048421: 89 04 24 mov %eax,(%esp) 8048424: e8 eb fe ff ff call 8048314 <execve@plt> 8048429: c7 04 24 00 00 00 00 movl $0x0,(%esp)
But if you use something that executes a payload it uses int 0x80.
Sample C code :
#include <unistd.h>
char shellcode[] = "\x31\xc0\xb0\x46\x31\xdb\x31\xc9\xcd\x80\xeb\x16" "\x5b\x31\xc0\x88\x43\x07\x89\x5b\x08\x89\x43\x0c" "\xb0\x0b\x8d\x4b\x08\x8d\x53\x0c\xcd\x80\xe8\xe5" "\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68\x4e\x41" "\x41\x41\x41\x42\x42\x42\x42";
int main () {
int (func)();
func = (int ()()) shellcode;
(int)(func)(); }
objdump -D will give you that: 0804a040 <shellcode>: 804a040: 31 c0 xor %eax,%eax 804a042: b0 46 mov $0x46,%al 804a044: 31 db xor %ebx,%ebx 804a046: 31 c9 xor %ecx,%ecx 804a048: cd 80 int $0x80 804a04a: eb 16 jmp 804a062 <shellcode+0x22> 804a04c: 5b pop %ebx 804a04d: 31 c0 xor %eax,%eax 804a04f: 88 43 07 mov %al,0x7(%ebx) 804a052: 89 5b 08 mov %ebx,0x8(%ebx) 804a055: 89 43 0c mov %eax,0xc(%ebx) 804a058: b0 0b mov $0xb,%al 804a05a: 8d 4b 08 lea 0x8(%ebx),%ecx 804a05d: 8d 53 0c lea 0xc(%ebx),%edx 804a060: cd 80 int $0x80 804a062: e8 e5 ff ff ff call 804a04c <shellcode+0xc>
I guess you can force it, but in general the compiler will replace it with calls to libs.
but...this is because printf != the write syscall
write(STDOUT, "Hello World!\n", len("Hello World!\n"));you are probably thinking of STDOUT_FILENO. can you just put "1" there?
also, reordering the "mov"s (so they appear in actual call order: edx, ecx, ebx) will simplify the diagram somewhat.