HTB - headache
64bit 실행 바이너리이다.
IDA 헥스레이로 분석이 불가능해서, 디버깅을 바로 시작한다.
gdb 디버깅을 하려고보니까 까다롭다.
IDA로 리눅스디버깅으로 진행한다.
맨 처음 init_proc() 하는 함수에 브레이크포인트를 걸고 진행하면,
진행되는 함수들을 볼 수 있다.
F7로 함수에 진입하고 디컴파일되지않는 영역들은 패킹하여 디컴파일을 하면
Initialinsing을 출력하는 함수를 확인할 수 있다.
그 후 Enter the key를 하는 부분이 있는데, 여기서 v6에 key를 입력받는다.
그 후 v6가 20자인지 파악하고,
sub_55E718B2B35F함수를 통해 앞서 저장한 v2~v4 (사실상 v2에 주르륵 저장한 값들이다.) 활용하여 연산을 한다.
그 후, v2와 v3들을 아래의 로직으로 연산한것이 플래그가 된다.
이를 해결하는 복호화하는 코드를 짜면, 플래그가 나온다.
v2 = [0x3A,0x0E,0x55,0x1C,0x0F,0x31,0x31,0x2A,0x55,0x11,0x2D,0x1C,0x12,0x46,0x0D,0x02,0x19,0x14,0x5C,0x51]
v4 = [0x65,0x79,0x65,0x6B,0x74,0x73,0x65,0x62,0x65,0x72,0x72,0x6F,0x66,0x72,0x65,0x76,0x64,0x78,0x6C,0x61]
flag = ''
for i in range(20):
res = v2[i]^v4[i]
flag += chr(res)
print(flag)
flag라고 예상되는 값들을 출력해보면, _w0w{BTH0c_st4ht}l00 인것을 알 수 있다.
뭔가 이상한데, 잘 생각해보면 v2나 v3에 들어있던 값들이 리틀엔디안으로 8바이트씩 되어있으니까 저렇게 나온것이라는 것을 알 수 있다.
잘 정렬해보면...
HTB{w0w_th4ts_c000l}
누가봐도 플래그인데, 이것도 플래그가 아니다.
뭐가 잘못됐는지 보니까, 안티디버깅이 있다고한다.
위에서한 분석 내용은 return sub_55AF0A42D3C1()으로 분기하여, 분석한 내용이다.
앞에서 나온 fake flag를 입력하면 Login success!라고 뜨고, 프로그램이 종료되는데
디버깅을 하지않고 그냥 바이너리를 실행해서 저 플래그를 넣어주면 Login Failed가 뜬다.
그러다가 아래의 for문에 관심이 가게되었다.
이 부분으로 분기하기 위해서는 형광펜 친부분으로 분기하면 된다.
그러면 v7에 어떤 문자열아 박히는데 그 문자열을 보면,
HTB{th4t_w4s_h4rd}라는 문자열이 나온다.
이게 진짜 플래그인가? 했는데 이것도 아니라고한다.
안티디버깅을 우회한적이 없는것같아서 안티디버깅을 우회할 수 있는 곳으로 다시 거슬러올라가보자.
이 함수에 대해서 알아보지는 않았는데, syscall함수에서 안티디버깅을 체크한다.
안티디버깅을 체크한 반환값을 rbp+var_4에 저장하는데, 여기서 rax를 0으로 바꿔서 저장시키면 안티디버깅이 우회된다.
그리고 위와같이 똑같이 프로그램을 실행시킨다.
실행시킬때는 HTB{w0w_th4ts_c000l}를 입력해준다.
입력해주고 디버깅을 진행해본다.(cmp위주로 보는 것이 좋다.)
디버깅을 통해 쭉쭉 내려가다보면,
cmp edx,eax 에서 플래그를 비교하는 것을 알 수 있다.
저 부분에 브레이크 포인트를 걸고 eax를 확인하거나,
rbp-0x19부분에 스택값을 확인해보면 플래그를 알 수 있다.
v7 = [0x48, 0x54, 0x42, 0x7B, 0x6C, 0x34, 0x79, 0x6C, 0x33, 0x5F, 0x77, 0x34, 0x73, 0x5F, 0x68, 0x33, 0x72, 0x33, 0x21, 0x7D]
flag = ''
for i in v7:
flag+=chr(i)
print (flag)
HTB{l4yl3_w4s_h3r3!}