[문제]


[풀이]

  • 64bit 바이너리
  • 카나리 없음
  • NX bit 존재
  • PIE 없음

 

바이너리 실행

  • Input Key로 사용자의 입력을 받음
  • 입력 값을 사전에 등록되어 있는 값과 비교하는 것으로 보임
  • 올바르지 않은 입력을 주었을 때 Nah... 메시지 출력하며 바이너리 종료

 

IDA 분석 - main 함수

int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
{
  unsigned int v3; // eax@1
  int v4; // [rsp+0h] [rbp-10h]@1
  int v5; // [rsp+4h] [rbp-Ch]@1
  __int64 v6; // [rsp+8h] [rbp-8h]@1

  v6 = *MK_FP(__FS__, 40LL);
  setbuf(_bss_start, 0LL);
  v4 = 0;
  v3 = time(0LL);
  srand(v3);
  v5 = rand();
  puts("============================");
  puts("======= 인증 프로그램 ======");
  puts("============================");
  printf("Input Key : ", 0LL, *(_QWORD *)&v4, v6);
  __isoc99_scanf("%d", &v4);
  if ( v5 == v4 )
  {
    puts("Correct!");
    system("cat /home/random/flag");
    exit(0);
  }
  puts("Nah...");
  exit(0);
}
  • rand 함수 호출 후 해당 값이 사용자의 입력 값과 같다면 flag 출력
  • rand 함수에 seed 값을 주지 않아 최초 호출된 값으로 고정된 random 값을 가진다는 것을 알 수 있음

 

gdb 분석 - 함수 주소

pwndbg> info func
All defined functions:

Non-debugging symbols:
0x00000000004005e8  _init
0x0000000000400620  puts@plt
0x0000000000400630  setbuf@plt
0x0000000000400640  system@plt
0x0000000000400650  printf@plt
0x0000000000400660  __libc_start_main@plt
0x0000000000400670  srand@plt
0x0000000000400680  time@plt
0x0000000000400690  __isoc99_scanf@plt
0x00000000004006a0  exit@plt
0x00000000004006b0  rand@plt
0x00000000004006c0  __gmon_start__@plt
0x00000000004006d0  _start
0x0000000000400700  deregister_tm_clones
0x0000000000400740  register_tm_clones
0x0000000000400780  __do_global_dtors_aux
0x00000000004007a0  frame_dummy
0x00000000004007c6  main
0x00000000004008a0  __libc_csu_init
0x0000000000400910  __libc_csu_fini
0x0000000000400914  _fini
  • main: 0x4007c6

gdb 분석 - main 함수

pwndbg> disass main
Dump of assembler code for function main:
   0x00000000004007c6 <+0>:	push   rbp
   0x00000000004007c7 <+1>:	mov    rbp,rsp
   0x00000000004007ca <+4>:	sub    rsp,0x10
   0x00000000004007ce <+8>:	mov    rax,QWORD PTR fs:0x28
   0x00000000004007d7 <+17>:	mov    QWORD PTR [rbp-0x8],rax
   0x00000000004007db <+21>:	xor    eax,eax
   0x00000000004007dd <+23>:	mov    rax,QWORD PTR [rip+0x200894]        # 0x601078 <stdout@@GLIBC_2.2.5>
   0x00000000004007e4 <+30>:	mov    esi,0x0
   0x00000000004007e9 <+35>:	mov    rdi,rax
   0x00000000004007ec <+38>:	call   0x400630 <setbuf@plt>
   0x00000000004007f1 <+43>:	mov    DWORD PTR [rbp-0xc],0x0
   0x00000000004007f8 <+50>:	mov    DWORD PTR [rbp-0x10],0x0
   0x00000000004007ff <+57>:	mov    edi,0x0
   0x0000000000400804 <+62>:	mov    eax,0x0
   0x0000000000400809 <+67>:	call   0x400680 <time@plt>
   0x000000000040080e <+72>:	mov    edi,eax
   0x0000000000400810 <+74>:	call   0x400670 <srand@plt>
   0x0000000000400815 <+79>:	call   0x4006b0 <rand@plt>
   0x000000000040081a <+84>:	mov    DWORD PTR [rbp-0xc],eax
   0x000000000040081d <+87>:	mov    edi,0x400928
   0x0000000000400822 <+92>:	call   0x400620 <puts@plt>
   0x0000000000400827 <+97>:	mov    edi,0x400948
   0x000000000040082c <+102>:	call   0x400620 <puts@plt>
   0x0000000000400831 <+107>:	mov    edi,0x400928
   0x0000000000400836 <+112>:	call   0x400620 <puts@plt>
   0x000000000040083b <+117>:	mov    edi,0x40096b
   0x0000000000400840 <+122>:	mov    eax,0x0
   0x0000000000400845 <+127>:	call   0x400650 <printf@plt>
   0x000000000040084a <+132>:	lea    rax,[rbp-0x10]
   0x000000000040084e <+136>:	mov    rsi,rax
   0x0000000000400851 <+139>:	mov    edi,0x400978
   0x0000000000400856 <+144>:	mov    eax,0x0
   0x000000000040085b <+149>:	call   0x400690 <__isoc99_scanf@plt>
   0x0000000000400860 <+154>:	mov    eax,DWORD PTR [rbp-0x10]
   0x0000000000400863 <+157>:	cmp    DWORD PTR [rbp-0xc],eax
   0x0000000000400866 <+160>:	jne    0x400886 <main+192>
   0x0000000000400868 <+162>:	mov    edi,0x40097b
   0x000000000040086d <+167>:	call   0x400620 <puts@plt>
   0x0000000000400872 <+172>:	mov    edi,0x400984
   0x0000000000400877 <+177>:	call   0x400640 <system@plt>
   0x000000000040087c <+182>:	mov    edi,0x0
   0x0000000000400881 <+187>:	call   0x4006a0 <exit@plt>
   0x0000000000400886 <+192>:	mov    edi,0x40099a
   0x000000000040088b <+197>:	call   0x400620 <puts@plt>
   0x0000000000400890 <+202>:	mov    edi,0x0
   0x0000000000400895 <+207>:	call   0x4006a0 <exit@plt>
End of assembler dump.
  • rand함수를 호출하는 main+84에 bp 걸어 eax로 반환되는 random 값 확인

  • random 값: 0x39a30760

→ 그러나 seed 값으로 인해 매번 다른 random 값 호출

→ random 값을 직접 만들어 exploit 해야함.

 

문제 해결

💡 - rand 함수는 seed 값이 같다면 동일한 난수를 출력함
- 서버에 접속 시 생성되는 난수와 동일한 시간에 난수를 생성하여 사용자에게 출력해준다면 난수가 무엇인지 알 수 있을 것

 

방법1 - 난수 생성 코드 작성

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

void main(){
        srand(time(NULL));
        printf("%d", rand());
        return 0;
}

  • ;으로 난수 생성 바이너리와 서버 접속을 연속으로 진행한다면 난수를 가시적으로 확인할 수 있음

 

방법2 - 공유 객체 파일 생성

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

void main(){
        srand(time(NULL));
        int random = rand();
        return random;
}
  • 1번과 동일한 소스코드로는 exploit 불가(return 값이 0이 되면 안됨)

  • 공유 객체 파일로 컴파일

 

Python2

from pwn import *
from ctypes import *

code = CDLL('./rand.so')
random = code.main() #c코드에서의 함수이름 작성

p = remote("ctf.j0n9hyun.xyz",3014)
e = ELF("./random")

p.recvuntil(" : ")
p.sendline(str(random))
p.interactive()
💡 ctypes 라이브러리
파이썬용 외부 함수(foreign function) 라이브러리
C 호환 데이터형을 제공하며, DLL 또는 공유 라이브러리에 있는 함수를 호출할 수 있음.
C로 작성된 코드가 Shared Object(.so)의 형태로 컴파일 되어 있어야 함.
CDLL로 파이썬과 C를 연결할 수 있음


flag

🍒  HackCTF{5087686686858549173307745189}

 

'Wargame > HackCTF' 카테고리의 다른 글

[HackCTF] Poet  (0) 2022.10.30
[HackCTF] 1996  (0) 2022.10.30
[HackCTF] RTL_Core  (0) 2022.10.30
[HackCTF] Beginner_Heap  (0) 2022.10.30
[HackCTF] Look at me  (0) 2022.10.30

+ Recent posts