Dreamhack/Dreamhack Wargame (Challenge)

[97] IT 비전공자 [dreamhack]Small Counter문제 풀기

imaginefuture-1 2024. 12. 15. 10:18

오랜만에 뤼버씽!

 

 

ida 드가자~

 

 

 

이 코드는 간단한 프로그램으로 보이며, 리버싱 문제에서 자주 볼 수 있는 구조를 가지고 있습니다. 주된 목표는 프로그램의 동작을 분석하여 숨겨진 문자열(플래그)을 찾거나, 프로그램의 의도된 동작을 이해하는 것입니다.


코드 분석

1. 변수 초기화

_QWORD src[10]; // [rsp+0h] [rbp-F0h] BYREF
_BYTE dest[72]; // [rsp+A0h] [rbp-50h] BYREF
int i;          // [rsp+ECh] [rbp-4h]
  • src:
    • 64비트 크기의 _QWORD 배열로 선언된 임시 저장소입니다.
    • 크기는 10 × 8바이트 = 80바이트입니다.
  • dest:
    • 72바이트 크기의 _BYTE 배열로 선언된 버퍼입니다.
  • i:
    • 카운터 변수로 사용되며, 초기값은 10입니다.

2. 프로그램의 흐름

  1. 출력 메시지:
    • 콘솔에 "---Counter---" 메시지를 출력합니다.
  2. puts("---Counter---");
  3. for 루프:
    • i의 값이 10에서 1까지 감소하면서, 현재 값을 출력합니다.
  4. for ( i = 10; i > 0; --i ) { printf("%d\n", i); ... }
  5. 조건문:
    • i가 3일 때:
      • 문자열 "IM{508889j32j87j9jg54650840428hjhi2ii08h74ihj538h543j7g6k5jk8jih22f}"을 src 배열에 복사합니다.
      • memcpy를 사용하여 src의 0x45 바이트(69바이트)를 dest에 복사합니다.
  6. if ( i == 3 ) { strcpy((char *)src, "IM{508889j32j87j9jg54650840428hjhi2ii08h74ihj538h543j7g6k5jk8jih22f}"); memcpy(dest, src, 0x45uLL); }
  7. 종료 메시지:
    • 콘솔에 "---END---" 메시지를 출력합니다.
  8. puts("---END---");
  9. 반환값:
    • 프로그램은 정상 종료됩니다.
  10. return 0;

숨겨진 정보: 플래그

strcpy 함수에서 프로그램이 특정 조건에서 복사하는 문자열이 플래그처럼 보입니다:

"IM{508889j32j87j9jg54650840428hjhi2ii08h74ihj538h543j7g6k5jk8jih22f}"

동작 확인

  1. for 루프에서 i == 3 조건을 만족할 때만 플래그 문자열이 src에 복사되고, 이후 dest로 복사됩니다.
  2. 이후 dest 배열에 복사된 플래그 문자열이 프로그램에서 출력되거나 추가적으로 처리되지는 않습니다.

리버싱 및 취약점

1. 플래그 추출

  • 코드를 리버싱하거나 디버깅 없이도, 플래그 문자열은 코드 내에 명시적으로 포함되어 있으므로 쉽게 추출 가능합니다:
    IM{508889j32j87j9jg54650840428hjhi2ii08h74ihj538h543j7g6k5jk8jih22f}
    

2. 메모리 취약점 가능성

  • memcpy(dest, src, 0x45uLL):
    • dest는 72바이트 크기지만, 0x45(69) 바이트가 복사되므로 버퍼 오버플로우는 발생하지 않습니다.
    • 그러나 src의 크기가 충분히 크지 않다면 오버플로우가 발생할 가능성이 있습니다.
    • 이 코드에서는 src가 80바이트로 충분하므로 문제는 발생하지 않습니다.

리버싱 과정

  1. 목적 확인:
    • 플래그 문자열을 찾는 문제로 보입니다.
    • 코드를 리버싱하거나 디버깅하지 않아도 플래그 문자열이 소스 코드에 직접 명시되어 있습니다.
  2. 코드 실행:
    • puts 및 printf로 출력되는 메시지를 통해 프로그램 동작을 확인할 수 있습니다.
    • 디버깅을 통해 조건문(i == 3)이 실행되는 순간 메모리를 검사하여 src나 dest 배열에서 플래그를 확인할 수 있습니다.

요약

  • 프로그램은 카운트다운(10~1)과 함께 특정 조건에서 플래그 문자열을 복사합니다.
  • 코드 내에 플래그 문자열이 명시적으로 포함되어 있어, 소스 코드만으로도 쉽게 추출 가능합니다.
  • 보안적인 관점에서, 플래그 문자열이 하드코딩되어 있으므로 리버싱 도구 없이도 쉽게 접근할 수 있는 문제가 있습니다.

플래그:

IM{508889j32j87j9jg54650840428hjhi2ii08h74ihj538h543j7g6k5jk8jih22f}

 

 

지피티님.. 아직..인간은 그렇게 호락호락하지않습니다..

 

 

 

FLAG_GEN은 rbp+var_4가 5이면 호출된다

 

 

 

 

(gdb) disassemble main
Dump of assembler code for function main:
   0x0000555555555494 <+0>:	endbr64
   0x0000555555555498 <+4>:	push   %rbp
   0x0000555555555499 <+5>:	mov    %rsp,%rbp
   0x000055555555549c <+8>:	sub    $0xf0,%rsp
   0x00005555555554a3 <+15>:	movl   $0x0,-0x4(%rbp)
   0x00005555555554aa <+22>:	lea    0xb53(%rip),%rax        # 0x555555556004
   0x00005555555554b1 <+29>:	mov    %rax,%rdi
   0x00005555555554b4 <+32>:	call   0x555555555090 <puts@plt>
   0x00005555555554b9 <+37>:	movl   $0xa,-0x4(%rbp)
   0x00005555555554c0 <+44>:	jmp    0x5555555555a0 <main+268>
   0x00005555555554c5 <+49>:	mov    -0x4(%rbp),%eax
   0x00005555555554c8 <+52>:	mov    %eax,%esi
   0x00005555555554ca <+54>:	lea    0xb41(%rip),%rax        # 0x555555556012
   0x00005555555554d1 <+61>:	mov    %rax,%rdi
   0x00005555555554d4 <+64>:	mov    $0x0,%eax
   0x00005555555554d9 <+69>:	call   0x5555555550b0 <printf@plt>
   0x00005555555554de <+74>:	cmpl   $0x3,-0x4(%rbp)
   0x00005555555554e2 <+78>:	jne    0x55555555559c <main+264>
   0x00005555555554e8 <+84>:	movabs $0x38383830357b4d49,%rax
   0x00005555555554f2 <+94>:	movabs $0x6a37386a32336a39,%rdx
   0x00005555555554fc <+104>:	mov    %rax,-0xf0(%rbp)
   0x0000555555555503 <+111>:	mov    %rdx,-0xe8(%rbp)
--Type <RET> for more, q to quit, c to continue without paging--ret
   0x000055555555550a <+118>:	movabs $0x3035363435676a39,%rax
   0x0000555555555514 <+128>:	movabs $0x6a68383234303438,%rdx
   0x000055555555551e <+138>:	mov    %rax,-0xe0(%rbp)
   0x0000555555555525 <+145>:	mov    %rdx,-0xd8(%rbp)
   0x000055555555552c <+152>:	movabs $0x6838306969326968,%rax
   0x0000555555555536 <+162>:	movabs $0x3833356a68693437,%rdx
   0x0000555555555540 <+172>:	mov    %rax,-0xd0(%rbp)
   0x0000555555555547 <+179>:	mov    %rdx,-0xc8(%rbp)
   0x000055555555554e <+186>:	movabs $0x3667376a33343568,%rax
   0x0000555555555558 <+196>:	movabs $0x68696a386b6a356b,%rdx
   0x0000555555555562 <+206>:	mov    %rax,-0xc0(%rbp)
   0x0000555555555569 <+213>:	mov    %rdx,-0xb8(%rbp)
   0x0000555555555570 <+220>:	movl   $0x7d663232,-0xb0(%rbp)
   0x000055555555557a <+230>:	movb   $0x0,-0xac(%rbp)
   0x0000555555555581 <+237>:	lea    -0xf0(%rbp),%rcx
   0x0000555555555588 <+244>:	lea    -0x50(%rbp),%rax
   0x000055555555558c <+248>:	mov    $0x45,%edx
   0x0000555555555591 <+253>:	mov    %rcx,%rsi
   0x0000555555555594 <+256>:	mov    %rax,%rdi
   0x0000555555555597 <+259>:	call   0x5555555550c0 <memcpy@plt>
   0x000055555555559c <+264>:	subl   $0x1,-0x4(%rbp)
   0x00005555555555a0 <+268>:	cmpl   $0x0,-0x4(%rbp)
   0x00005555555555a4 <+272>:	jg     0x5555555554c5 <main+49>
--Type <RET> for more, q to quit, c to continue without paging--tet
   0x00005555555555aa <+278>:	cmpl   $0x5,-0x4(%rbp)
   0x00005555555555ae <+282>:	jne    0x5555555555fe <main+362>
   0x00005555555555b0 <+284>:	lea    0xa5f(%rip),%rax        # 0x555555556016
   0x00005555555555b7 <+291>:	mov    %rax,%rdi
   0x00005555555555ba <+294>:	call   0x555555555090 <puts@plt>
   0x00005555555555bf <+299>:	mov    -0x4(%rbp),%eax
   0x00005555555555c2 <+302>:	mov    %eax,-0x8(%rbp)
   0x00005555555555c5 <+305>:	mov    -0x8(%rbp),%edx
   0x00005555555555c8 <+308>:	lea    -0xa0(%rbp),%rcx
   0x00005555555555cf <+315>:	lea    -0x50(%rbp),%rax
   0x00005555555555d3 <+319>:	mov    %rcx,%rsi
   0x00005555555555d6 <+322>:	mov    %rax,%rdi
   0x00005555555555d9 <+325>:	call   0x5555555551c9 <flag_gen>
   0x00005555555555de <+330>:	lea    -0xa0(%rbp),%rax
   0x00005555555555e5 <+337>:	mov    %rax,%rsi
   0x00005555555555e8 <+340>:	lea    0xa2d(%rip),%rax        # 0x55555555601c
   0x00005555555555ef <+347>:	mov    %rax,%rdi
   0x00005555555555f2 <+350>:	mov    $0x0,%eax
   0x00005555555555f7 <+355>:	call   0x5555555550b0 <printf@plt>
   0x00005555555555fc <+360>:	jmp    0x55555555560d <main+377>
   0x00005555555555fe <+362>:	lea    0xa1c(%rip),%rax        # 0x555555556021
   0x0000555555555605 <+369>:	mov    %rax,%rdi
   0x0000555555555608 <+372>:	call   0x555555555090 <puts@plt>
--Type <RET> for more, q to quit, c to continue without paging--tet
   0x000055555555560d <+377>:	mov    $0x0,%eax
   0x0000555555555612 <+382>:	leave
   0x0000555555555613 <+383>:	ret

 

 

bp main+278해도 안먹혀서 그냥 주소로 넣어줬더니 bp가 잘걸렸다 

이후 rbp-4dp =5를 집어넣고 컨티뉴해준다

짜자잔