Shellcode 작성 김영성
CONTENTS INDEX 1 필요지식 2 Shellcode 작성방법 3 Shellcode 작성
CONTENTS 1] 필요지식 1 스택 2 레지스터 3 스택프레임 4 어셈블리 구조와 기본명령어 5 Systemcall
01│ Stack, Register, StackFrame contants 01
02│ 기본 어셈블리어 contants 01
2] Shellcode 작성방법 1. 원하는 코드를 C언어로 작성 2. 코드를 어셈블리어로 변환( gcc –s ) 3. 생성된 어셈블리어를 참조하여 필요한 부분만 이용하여 따로 작성 ( 문자열 상수의 경우 참조가 안되므로, 상대적인 주소로 바꿔줘서 작성 ) 4. 작성한 어셈블리어 코드를 바이너리 코드로 변경했을 때, NULL 이 포함되어있으면 NULL이 포함되지 않게 수정 (ex) movb 0x00, $eax -> xor $eax, $eax 5. ShellCode 작성 contants 01
3] Shellcode 작성 CONTENTS 1 C언어 코드 작성, 어셈변환 2 필요한 부분만 어셈블리어 재작성 2 필요한 부분만 어셈블리어 재작성 3 NULL이 포함된 바이너리 바꿔주기
01│ C언어 코드 작성, 어셈변환(1) main() { write(1,"I'm Willy in Null@Root\n",23); } [willy@Null@Root]$ gcc test21.c -o test21 -mpreferred-stack-boundary=2 -static [willy@Null@Root]$ gdb -q test21 (gdb) disassemble main Dump of assembler code for function main: 0x80481dc <main>: push %ebp 0x80481dd <main+1>: mov %esp,%ebp 0x80481df <main+3>: push $0x17 0x80481e1 <main+5>: push $0x808b1c8 0x80481e6 <main+10>: push $0x1 0x80481e8 <main+12>: call 0x804c390 <__libc_write> 0x80481ed <main+17>: add $0xc,%esp 0x80481f0 <main+20>: leave 0x80481f1 <main+21>: ret 0x80481f2 <main+22>: nop 0x80481f3 <main+23>: nop End of assembler dump. contants 01
01│ C언어 코드 작성, 어셈변환(2) (gdb) disassemble __libc_write Dump of assembler code for function __libc_write: 0x804c390 <__libc_write>: push %ebx 0x804c391 <__libc_write+1>: mov 0x10(%esp,1),%edx 0x804c395 <__libc_write+5>: mov 0xc(%esp,1),%ecx 0x804c399 <__libc_write+9>: mov 0x8(%esp,1),%ebx 0x804c39d <__libc_write+13>: mov $0x4,%eax 0x804c3a2 <__libc_write+18>: int $0x80 0x804c3a4 <__libc_write+20>: pop %ebx 0x804c3a5 <__libc_write+21>: cmp $0xfffff001,%eax 0x804c3aa <__libc_write+26>: jae 0x804cab0 <__syscall_error> 0x804c3b0 <__libc_write+32>: ret End of assembler dump. contants 01
02│ 필요한 부분만 어셈블리어 재작성(1) contants 01
02│ 필요한 부분만 어셈블리어 재작성(2) [willy@Null@Root]$ cat test23.s .LC0: .string "I'm Willy in Null@Root\n" .globl main main: movl $0x04, %eax movl $0x01, %ebx movl $.LC0, %ecx movl $0x17, %edx int $0x80 <--- write()를 위한 인터럽트 movl $0x01, %eax movl $0x00, %ebx int $0x80 <--- exit(0)을 위한 인터럽트 ret contants 01
02│ 필요한 부분만 어셈블리어 재작성(3) .globl main main: jmp strings start: popl %esi movl $0x04, %eax movl $0x01, %ebx movl %esi, %ecx movl $0x17, %edx int $0x80 movl $0x01, %eax movl $0x00, %ebx strings:call start .string "I'm Willy in Null@Root\n" contants 01
02│ 필요한 부분만 어셈블리어 재작성(4) char shell_code[] = 0804841c <main>: 804841c: eb 20 jmp 804843e <strings> 0804841e <start>: 804841e: 5e pop %esi 804841f: b8 04 00 00 00 mov $0x4,%eax 8048424: bb 01 00 00 00 mov $0x1,%ebx 8048429: 89 f1 mov %esi,%ecx 804842b: ba 17 00 00 00 mov $0x17,%edx 8048430: cd 80 int $0x80 8048432: b8 01 00 00 00 mov $0x1,%eax 8048437: bb 00 00 00 00 mov $0x0,%ebx 804843c: cd 80 int $0x80 0804843e <strings>: 804843e: e8 db ff ff ff call 804841e <start> 8048443: 49 dec %ecx 8048444: 27 daa 8048445: 6d insl (%dx),%es:(%edi) 8048446: 20 57 69 and %dl,0x69(%edi) 8048449: 6c insb (%dx),%es:(%edi) 804844a: 6c insb (%dx),%es:(%edi) 804844b: 79 20 jns 804846d <__do_global_ctors_aux+0xd> 804844d: 69 6e 20 4e 75 6c 6c imul $0x6c6c754e,0x20(%esi),%ebp 8048454: 40 inc %eax 8048455: 52 push %edx 8048456: 6f outsl %ds:(%esi),(%dx) 8048457: 6f outsl %ds:(%esi),(%dx) 8048458: 74 0a je 8048464 <__do_global_ctors_aux+0x4> char shell_code[] = "\xeb\x20\x5e\xb8\x04\x00\x00\x00\xbb\x01\x00\x00\x00\x89\xf1\xba\x17\x00\x00\x00" "\xcd\x80\xb8\x01\x00\x00\x00\xbb\x00\x00\x00\x00\xcd\x80\xe8\xdb\xff\xff\xff" "I'm willy in Null@Root\n"; contants 01
03│ NULL 이 포함된 바이너리코드 바꿔주기(1) contants 01
03│ NULL 이 포함된 바이너리코드 바꿔주기(2) 0804841c <main>: 804841c: eb 17 jmp 8048435 <strings> 0804841e <start>: 804841e: 5e pop %esi 804841f: 31 c0 xor %eax,%eax 8048421: 31 db xor %ebx,%ebx 8048423: 31 d2 xor %edx,%edx 8048425: b0 04 mov $0x4,%al 8048427: b3 01 mov $0x1,%bl 8048429: 89 f1 mov %esi,%ecx 804842b: b2 17 mov $0x17,%dl 804842d: cd 80 int $0x80 804842f: b0 01 mov $0x1,%al 8048431: 31 db xor %ebx,%ebx 8048433: cd 80 int $0x80 08048435 <strings>: 8048435: e8 e4 ff ff ff call 804841e <start> 804843a: 49 dec %ecx 804843b: 27 daa 804843c: 6d insl (%dx),%es:(%edi) 804843d: 20 57 69 and %dl,0x69(%edi) 8048440: 6c insb (%dx),%es:(%edi) 8048441: 6c insb (%dx),%es:(%edi) 8048442: 79 20 jns 8048464 <__do_global_ctors_aux+0x4> 8048444: 69 6e 20 4e 75 6c 6c imul $0x6c6c754e,0x20(%esi),%ebp 804844b: 40 inc %eax 804844c: 52 push %edx 804844d: 6f outsl %ds:(%esi),(%dx) 804844e: 6f outsl %ds:(%esi),(%dx) 804844f: 74 0a je 804845b <strings+0x26> contants 01
03│ NULL 이 포함된 바이너리코드 바꿔주기(3) [willy@Null@Root]$ cat test42.c char print_code[] = "\xeb\x17\x5e\x31\xc0\x31\xdb\x31\xd2\xb0\x04\xb3\x01\x89\xf1" "\xb2\x17\xcd\x80\xb0\x01\x31\xdb\xcd\x80\xe8\xe4\xff\xff\xff" "I'm willy in Null@Root\n"; main() { int *ret; ret = (int *)&ret + 2; (*ret) = (int)print_code; } [willy@Null@Root]$ gcc test42.c -o test42 [willy@Null@Root]$ ./test42 I'm willy in Null@Root contants 01
Shell을 띄우기 위해서는? main() { char *name[2]; name[0] = "/bin/sh"; -> System(), exec(), execve() ….등 쉘을 띄울 수 있는 함수를 이용 main() { char *name[2]; name[0] = "/bin/sh"; name[1] = NULL; execve(name[0],name,NULL); } contants 01
참고자료 *** How to make shellcode in linux for beginners *** by Willy in Null@Root contants 01
THANK YOU