flag_gen() 함수를 실행하는 것이 목표다. 이게 왜 목표지?
일단 냅다 실행부터 해보자
음 일단 모르겠다.

이 main함수 디컴파일 내용만 보면 방금 출력은 납득이 된다. 근데 저 IM{...}은 복사만 되고 어디에 들어가지를 않는다. 
IDA 왼쪽에는 Function name을 찾을 수 있다. 저기 flag_gen이 보인다.

일단 이게 flag를 생성하는 거 같다. rax에 result를 반환하는 것 같다.
gdb로 디버깅을 해보자.
$ gdb chall
일단 main 함수를 살펴보자
$ disassemble main
Dump of assembler code for function main:
0x0000000000001494 <+0>: endbr64
0x0000000000001498 <+4>: push rbp
0x0000000000001499 <+5>: mov rbp,rsp
0x000000000000149c <+8>: sub rsp,0xf0
0x00000000000014a3 <+15>: mov DWORD PTR [rbp-0x4],0x0
0x00000000000014aa <+22>: lea rax,[rip+0xb53] # 0x2004
0x00000000000014b1 <+29>: mov rdi,rax
0x00000000000014b4 <+32>: call 0x1090 <puts@plt>
0x00000000000014b9 <+37>: mov DWORD PTR [rbp-0x4],0xa
0x00000000000014c0 <+44>: jmp 0x15a0 <main+268>
0x00000000000014c5 <+49>: mov eax,DWORD PTR [rbp-0x4]
0x00000000000014c8 <+52>: mov esi,eax
0x00000000000014ca <+54>: lea rax,[rip+0xb41] # 0x2012
0x00000000000014d1 <+61>: mov rdi,rax
0x00000000000014d4 <+64>: mov eax,0x0
0x00000000000014d9 <+69>: call 0x10b0 <printf@plt>
0x00000000000014de <+74>: cmp DWORD PTR [rbp-0x4],0x3
0x00000000000014e2 <+78>: jne 0x159c <main+264>
0x00000000000014e8 <+84>: movabs rax,0x38383830357b4d49
0x00000000000014f2 <+94>: movabs rdx,0x6a37386a32336a39
0x00000000000014fc <+104>: mov QWORD PTR [rbp-0xf0],rax
0x0000000000001503 <+111>: mov QWORD PTR [rbp-0xe8],rdx
0x000000000000150a <+118>: movabs rax,0x3035363435676a39
0x0000000000001514 <+128>: movabs rdx,0x6a68383234303438
0x000000000000151e <+138>: mov QWORD PTR [rbp-0xe0],rax
0x0000000000001525 <+145>: mov QWORD PTR [rbp-0xd8],rdx
0x000000000000152c <+152>: movabs rax,0x6838306969326968
0x0000000000001536 <+162>: movabs rdx,0x3833356a68693437
0x0000000000001540 <+172>: mov QWORD PTR [rbp-0xd0],rax
0x0000000000001547 <+179>: mov QWORD PTR [rbp-0xc8],rdx
0x000000000000154e <+186>: movabs rax,0x3667376a33343568
0x0000000000001558 <+196>: movabs rdx,0x68696a386b6a356b
0x0000000000001562 <+206>: mov QWORD PTR [rbp-0xc0],rax
0x0000000000001569 <+213>: mov QWORD PTR [rbp-0xb8],rdx
0x0000000000001570 <+220>: mov DWORD PTR [rbp-0xb0],0x7d663232
0x000000000000157a <+230>: mov BYTE PTR [rbp-0xac],0x0
0x0000000000001581 <+237>: lea rcx,[rbp-0xf0]
0x0000000000001588 <+244>: lea rax,[rbp-0x50]
0x000000000000158c <+248>: mov edx,0x45
0x0000000000001591 <+253>: mov rsi,rcx
0x0000000000001594 <+256>: mov rdi,rax
0x0000000000001597 <+259>: call 0x10c0 <memcpy@plt>
0x000000000000159c <+264>: sub DWORD PTR [rbp-0x4],0x1
0x00000000000015a0 <+268>: cmp DWORD PTR [rbp-0x4],0x0
0x00000000000015a4 <+272>: jg 0x14c5 <main+49>
0x00000000000015aa <+278>: cmp DWORD PTR [rbp-0x4],0x5
0x00000000000015ae <+282>: jne 0x15fe <main+362>
0x00000000000015b0 <+284>: lea rax,[rip+0xa5f] # 0x2016
0x00000000000015b7 <+291>: mov rdi,rax
0x00000000000015ba <+294>: call 0x1090 <puts@plt>
0x00000000000015bf <+299>: mov eax,DWORD PTR [rbp-0x4]
0x00000000000015c2 <+302>: mov DWORD PTR [rbp-0x8],eax
0x00000000000015c5 <+305>: mov edx,DWORD PTR [rbp-0x8]
0x00000000000015c8 <+308>: lea rcx,[rbp-0xa0]
0x00000000000015cf <+315>: lea rax,[rbp-0x50]
0x00000000000015d3 <+319>: mov rsi,rcx
0x00000000000015d6 <+322>: mov rdi,rax
0x00000000000015d9 <+325>: call 0x11c9 <flag_gen>
0x00000000000015de <+330>: lea rax,[rbp-0xa0]
0x00000000000015e5 <+337>: mov rsi,rax
0x00000000000015e8 <+340>: lea rax,[rip+0xa2d] # 0x201c
0x00000000000015ef <+347>: mov rdi,rax
0x00000000000015f2 <+350>: mov eax,0x0
0x00000000000015f7 <+355>: call 0x10b0 <printf@plt>
0x00000000000015fc <+360>: jmp 0x160d <main+377>
0x00000000000015fe <+362>: lea rax,[rip+0xa1c] # 0x2021
0x0000000000001605 <+369>: mov rdi,rax
0x0000000000001608 <+372>: call 0x1090 <puts@plt>
0x000000000000160d <+377>: mov eax,0x0
0x0000000000001612 <+382>: leave
0x0000000000001613 <+383>: ret
flag_gen이 main+325에 보인다. 근데 main+264부터 main+282를 보면
[rbp-4]에서 1을 빼고 0과 비교해서 rip를 이동시키는 것을 볼 수 있다. 아마 main함수의 for문에서 --i를 수행하고 0과 비교하는 부분인것 같다.
근데 i를 갑자기 5하고 비교하고 같지 않으면 rip를 main+362로 날려버린다.(이후 프로그램 종료) 그 결과 flag_gen함수를 건너뛰어버리니 함수를 실행하지 않는 것이다.
그래서 IDA로 main+282를 jne에서 je로 바꾸어 flag를 실행했으나, IM{...}이 출력된다.
플래그는 DH{}형식이다. Nice를 외쳐주니 일단 함수 호출은 이뤄진 것 같다. 이후 조금 힌트를 얻어보니 flag_gen함수가 인자를 3개 받는다고 한다.

IDA 디컴파일 내용을 보니 진짜 그렇다. 다음부터는 함수의 인자를 잘 살펴보아야겠다.
실제로 main+299부터 살펴보면 rbp-4, 즉 i 를 edx에 옮기는 걸 볼 수있다.
즉 앞에서 5하고 i를 비교하는 것은 5를 함수 인자로 넘기기 위한 것이다.
방금 IDA에서 수정한 내용을 원상 복구하고, 프로그램을 실행하면서 바이너리 패치를 수행해보자.
먼저 분기점 main+282의 앞에 중단점을 설정하고 실행하자
$ b *main+278
$ r
일단 rbp의 주소를 알아보자
pwndbg> info registers rbp
rbp 0x7fffffffdd30 0x7fffffffdd30
오케이 그러면 rbp-4의 값을 5로 바꿔주자
pwndbg> set *(int*)(0x7fffffffdd30-4) = 5

무사히 넘어갔다 무사히 넘어간 것을 확인했으니, c로 나머지를 실행하면
pwndbg> c
Continuing.
Nice!
DH{...}
이 나온다.
(1) gdb, IDA 다루는 법이 아직 서툴다. 바이너리 패치하는 방법을 찾는데 들인 시간이 생각보다 컸다.
(2) 함수를 보면 어떤 인자를 받는지도 잘 살펴보고, 코드에서 작성자의 의도를 잘 살펴보아야겠다. 단순히 jne를 수정해서 넘어갔는데도 플래그가 나오지 않아서 당황스러웠다. i가 인자로 들어간다는 것을 알았으면 좀 더 빨리 풀 수 있었을 것이다.
(3) 다음에는 완전히 혼자만의 힘으로 문제를 풀 수 있기를 바란다.