상세 컨텐츠

본문 제목

[angr_ctf] 05_angr_symbolic_memory

SYSTEM HACKING/CTF, etc

by koharin 2022. 5. 14. 16:13

본문

728x90
반응형

파일 정보

$ file 05_angr_symbolic_memory 
05_angr_symbolic_memory: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=7fce021dfa8d22282d85297e98dd62a266eb5975, not stripped

 

 

코드 분석

.text:080485BF ; int __cdecl main(int argc, const char **argv, const char **envp)
.text:080485BF                 public main
.text:080485BF main            proc near               ; DATA XREF: _start+26↑o
.text:080485BF
.text:080485BF var_C           = dword ptr -0Ch
.text:080485BF var_4           = dword ptr -4
.text:080485BF argc            = dword ptr  8
.text:080485BF argv            = dword ptr  0Ch
.text:080485BF envp            = dword ptr  10h
.text:080485BF
.text:080485BF ; __unwind {
.text:080485BF                 lea     ecx, [esp+4]
.text:080485C3                 and     esp, 0FFFFFFF0h
.text:080485C6                 push    dword ptr [ecx-4]
.text:080485C9                 push    ebp
.text:080485CA                 mov     ebp, esp
.text:080485CC                 push    ecx
.text:080485CD                 sub     esp, 14h
.text:080485D0                 sub     esp, 4
.text:080485D3                 push    21h             ; n
.text:080485D5                 push    0               ; c
.text:080485D7                 push    offset user_input ; s
.text:080485DC                 call    _memset
.text:080485E1                 add     esp, 10h
.text:080485E4                 sub     esp, 0Ch
.text:080485E7                 push    offset aEnterThePasswo ; "Enter the password: "
.text:080485EC                 call    _printf
.text:080485F1                 add     esp, 10h
.text:080485F4                 sub     esp, 0Ch
.text:080485F7                 push    offset unk_AB232D8
.text:080485FC                 push    offset unk_AB232D0
.text:08048601                 push    offset unk_AB232C8
.text:08048606                 push    offset user_input
.text:0804860B                 push    offset a8s8s8s8s ; "%8s %8s %8s %8s"
.text:08048610                 call    ___isoc99_scanf
.text:08048615                 add     esp, 20h
.text:08048618                 mov     [ebp+var_C], 0
.text:0804861F                 jmp     short loc_804864E
.text:08048621 ; ---------------------------------------------------------------------------
.text:08048621
.text:08048621 loc_8048621:                            ; CODE XREF: main+93↓j
.text:08048621                 mov     eax, [ebp+var_C]
.text:08048624                 add     eax, 0AB232C0h
.text:08048629                 movzx   eax, byte ptr [eax]
.text:0804862C                 movsx   eax, al
.text:0804862F                 sub     esp, 8
.text:08048632                 push    [ebp+var_C]
.text:08048635                 push    eax
.text:08048636                 call    complex_function
.text:0804863B                 add     esp, 10h
.text:0804863E                 mov     edx, eax
.text:08048640                 mov     eax, [ebp+var_C]
.text:08048643                 add     eax, 0AB232C0h
.text:08048648                 mov     [eax], dl
.text:0804864A                 add     [ebp+var_C], 1
.text:0804864E
.text:0804864E loc_804864E:                            ; CODE XREF: main+60↑j
.text:0804864E                 cmp     [ebp+var_C], 1Fh
.text:08048652                 jle     short loc_8048621
.text:08048654                 sub     esp, 4
.text:08048657                 push    20h             ; n
.text:08048659                 push    offset s2       ; "OSIWHBXIFOQVSBZBISILSCLBIAXSEWUT"
.text:0804865E                 push    offset user_input ; s1
.text:08048663                 call    _strncmp
.text:08048668                 add     esp, 10h
.text:0804866B                 test    eax, eax
.text:0804866D                 jz      short loc_8048681
.text:0804866F                 sub     esp, 0Ch
.text:08048672                 push    offset s        ; "Try again."
.text:08048677                 call    _puts
.text:0804867C                 add     esp, 10h
.text:0804867F                 jmp     short loc_8048691
.text:08048681 ; ---------------------------------------------------------------------------
.text:08048681
.text:08048681 loc_8048681:                            ; CODE XREF: main+AE↑j
.text:08048681                 sub     esp, 0Ch
.text:08048684                 push    offset aGoodJob ; "Good Job."
.text:08048689                 call    _puts
.text:0804868E                 add     esp, 10h
.text:08048691
.text:08048691 loc_8048691:                            ; CODE XREF: main+C0↑j
.text:08048691                 mov     eax, 0
.text:08048696                 mov     ecx, [ebp+var_4]
.text:08048699                 leave
.text:0804869A                 lea     esp, [ecx-4]
.text:0804869D                 retn
.text:0804869D ; } // starts at 80485BF
.text:0804869D main            endp
int __cdecl main(int argc, const char **argv, const char **envp)
{
  signed int i; // [esp+Ch] [ebp-Ch]

  memset(user_input, 0, 0x21u);
  printf("Enter the password: ");
  __isoc99_scanf("%8s %8s %8s %8s", user_input, &unk_AB232C8, &unk_AB232D0, &unk_AB232D8);
  for ( i = 0; i <= 31; ++i )
    *(_BYTE *)(i + 179450560) = complex_function(*(char *)(i + 179450560), i);
  if ( !strncmp(user_input, "OSIWHBXIFOQVSBZBISILSCLBIAXSEWUT", 0x20u) )
    puts("Good Job.");
  else
    puts("Try again.");
  return 0;
}

scanf로 4개의 스트링을 입력받는다.

이후 strncmp로 0x20byte만큼 "OSIWHBXIFOQVSBZBISILSCLBIAXSEWUT”와 비교 후 동일하면 “Good Job.”을, 아니면 “Try again.”을 출력한다.

 

 

Exploit

set start state: Project.factory.blank_state

.text:080485FC                 push    offset unk_AB232D0
.text:08048601                 push    offset unk_AB232C8
.text:08048606                 push    offset user_input
.text:0804860B                 push    offset a8s8s8s8s ; "%8s %8s %8s %8s"
.text:08048610                 call    ___isoc99_scanf
.text:08048615                 add     esp, 20h
.text:08048618                 mov     [ebp+var_C], 0

이 문제에서도 scanf로 여러 입력을 받는데 angr는 이를 지원하지 않으므로 scanf 호출 다음으로 시작 주소를 준다.

state = p.factory.blank_state(
        addr=0x08048618,
        add_options={angr.options.SYMBOL_FILL_UNCONSTRAINED_MEMORY,
                     angr.options.SYMBOL_FILL_UNCONSTRAINED_REGISTERS}
)

 

set bitvectors

scanf로 4개의 스트링 입력을 받으므로, 입력값을 설정해줄 symbolic bitvector를 만들어준다.

# set bitvectors
input0 = state.solver.BVS('input0', 8*8)
input1 = state.solver.BVS('input1', 8*8)
input2 = state.solver.BVS('input2', 8*8)
input3 = state.solver.BVS('input3', 8*8)

 

set global variables: state.memory.store

scanf("%8s %8s %8s %8s", user_input, &unk_AB232C8, &unk_AB232D0, &unk_AB232D8);
.bss:0AB232C0 user_input      db 8 dup(?)             ; DATA XREF: main+18↑o
.bss:0AB232C0                                         ; main+47↑o ...
.bss:0AB232C8 unk_AB232C8     db    ? ;               ; DATA XREF: main+42↑o
.bss:0AB232C9                 db    ? ;
.bss:0AB232CA                 db    ? ;
.bss:0AB232CB                 db    ? ;
.bss:0AB232CC                 db    ? ;
.bss:0AB232CD                 db    ? ;
.bss:0AB232CE                 db    ? ;
.bss:0AB232CF                 db    ? ;
.bss:0AB232D0 unk_AB232D0     db    ? ;               ; DATA XREF: main+3D↑o
.bss:0AB232D1                 db    ? ;
.bss:0AB232D2                 db    ? ;
.bss:0AB232D3                 db    ? ;
.bss:0AB232D4                 db    ? ;
.bss:0AB232D5                 db    ? ;
.bss:0AB232D6                 db    ? ;
.bss:0AB232D7                 db    ? ;
.bss:0AB232D8 unk_AB232D8     db    ? ;

이번 문제에서는 입력값이 전역변수 user_input에 차례대로 저장된다.

첫 번째 입력값 주소는 0AB232C0, 두 번째부터 각각 0AB232C8, 0AB232D0, 0AB232D8이다. 각각 8byte 크기인걸 확인할 수 있다.

# set global variables with bitvectors
state.memory.store(0x0AB232C0, input0)
state.memory.store(0x0AB232C8, input1)
state.memory.store(0x0AB232D0, input2)
state.memory.store(0x0AB232D8, input3)

 

find solution

이후부터는 simulation manages의 explore를 사용해서 find, avoid로 solution을 찾아준다.

 

exploit result

#!/usr/bin/python 
import angr,sys

# create angr Project
p = angr.Project('./05_angr_symbolic_memory')

# set start state
state = p.factory.blank_state(
        addr=0x08048618,
        add_options={angr.options.SYMBOL_FILL_UNCONSTRAINED_MEMORY,
                     angr.options.SYMBOL_FILL_UNCONSTRAINED_REGISTERS}
)

# set bitvectors
input0 = state.solver.BVS('input0', 8*8)
input1 = state.solver.BVS('input1', 8*8)
input2 = state.solver.BVS('input2', 8*8)
input3 = state.solver.BVS('input3', 8*8)

# set global variables with bitvectors
state.memory.store(0x0AB232C0, input0)
state.memory.store(0x0AB232C8, input1)
state.memory.store(0x0AB232D0, input2)
state.memory.store(0x0AB232D8, input3)

# create simulation managers
simgr = p.factory.simgr(state)

# search possible path to find solution
simgr.explore(find=lambda s: 'Good'.encode() in s.posix.dumps(sys.stdout.fileno()), avoid=lambda s: 'Try'.encode() in s.posix.dumps(sys.stdout.fileno()))

if simgr.found:
    solution_state = simgr.found[0]
    print('solution state:', end=' ')

    solution0 = solution_state.solver.eval(input0, cast_to=bytes).decode()
    solution1 = solution_state.solver.eval(input1, cast_to=bytes).decode()
    solution2 = solution_state.solver.eval(input2, cast_to=bytes).decode()
    solution3 = solution_state.solver.eval(input3, cast_to=bytes).decode()

    print("%s %s %s %s" % (solution0, solution1, solution2, solution3))
else:
    raise Exception('could not find the solution')

728x90
반응형

관련글 더보기