이제까지 거의 웹만 풀다보니 다른거 해보고싶기도 했고,
이번학기에 컴시와 악성 들으면서 이젠 리버싱 하면 조금은 알아들을 것 같아서 해봤다!
correct를 출력하는 입력값을 찾으면 된다!
파일을 실행해서 Input:
에 뭔가 입력하면 Wrong
을 출력한다
IDA로 파일 열면 아래 창이 뜨는데 여기서 간단한 정보를 얻을 수 있다
바이너리의 아키텍처는 AMD64 (x86-64)
이고, 파일 포맷은 PE (Portable Executable)
구조라는 것을 알 수 있다
아무것도 바꾸지말고 그냥 OK 누르면 된다
그 다음은 디버깅 정보를 담고있는 심볼을 로드할거냐는 질문창이 뜨는데
따로 제공된 심볼(.pdb)가 없으므로 No를 누르면 된다
위에서 파일을 실행해본 결과 입력한 문자열을 검증한다는 사실을 알아냈다
따라서 검증 위치를 찾기 위해 파일이 실행될 때 출력되던 문자열을 검색해본다
View - Open subviews -> Strings
를 클릭해서 바이너리에 포함된 문자열을 조회한다
우리가 찾던 Correct
도 있었다!
상호 참조(Cross Reference, xref)를 통해 "Correct" 문자열이 사용되는 곳을 확인한다
다음과 같이 main
에서 참조되는 것을 알 수 있다
F5를 이용해서 Correct 문자열을 사용하는 main을 디컴파일한다
어떤 조건을 만족시켜야 Correct가 출력되는지 분석해본다
6번째 줄을 보면 sub_140001190
함수에 Input:
을 넘겨주고 있다
아마 출력하는 함수일 것이라는 추측을 할 수 있다
7번째 줄은 sub_1400011F0
함수인데 그 다음줄에 if문으로 검증하고 있으므로 여기서 사용자의 입력을 받는 것 같다
마지막으로 8번째 줄에서 사용된 sub_140001000
함수의 반환값에 따라 실제로 검증하는 과정을 거치는 것 같다
위에서 사용된 3개의 함수를 각각 디컴파일해서 하나씩 분석해보자
다음은 디컴파일 된 sub_140001190
함수이다
va_start
함수와 _acrt_iob_func(1);
함수가 사용되는 것으로 보아 printf
함수임을 알 수 있다
디컴파일 된 sub_1400011F0
도 위의 함수와 마찬가지로 va_start
함수를 통해 가변 인자를 받지만
__acrt_iob_func
함수의 인자가 0으로, stdin
스트림을 가져오게 되고,
따라서 printf
의 반대되는 함수인 scanf
함수이다
디컴파일 된 sub_140001000
을 보면 전달받은 인자를 strcmp
로 특정 문자열(여기서는 Compar3_the_str1ng
!!!)과 비교한다
만약 같으면 1을 반환하고 다르면 0을 반환한다
따라서 우리가 Compar3_the_str1ng
을 입력하면 Correct가 출력된다는 소리다
즉 Compar3_the_str1ng
가 flag이다!!
🔑 DH{Compar3_the_str1ng}
문제를 보면 위의 문제와 마찬가지로 correct를 출력하는 입력값을 알아내면 된다!
IDA로 파일 열어서 OK 누르고
No 누르기
프로그램이 로드되면 IDA가 자동으로 main 함수를 찾아서 보여준다
따라서 앞선 문제처럼 문자열 참조를 통해 main을 찾을 수도 있지만 IDA에서 자동으로 찾아주니 편하다
F5를 눌러 main 함수를 디컴파일한다
위의 문제와 구조가 거의 동일하다
따라서 sub_1400013E0
, sub_140001440
, sub_140001000
이 3가지 함수를 분석할 것이다
sub_1400013E0
을 디컴파일 한 모습이다
printf
와 굉장히 구조가 비슷하다
그런데 sub_1400013E0
함수 안에 또 다른 함수 sub_1400012B0
가 있다
sub_1400012B0
함수를 디컴파일하면 _stdio_common_vfprintf
함수를 호출하는 것을 알 수 있다
vfprintf
함수의 파일 스트림이 stdout
이기 때문에
결론적으로 sub_1400013E0
함수는 printf
임을 추측할 수 있다
다시 main으로 와서 알아보기 쉽게 sub_1400013E0
함수를 printf
로 이름 변경
(단축키 n 사용)
다음으로 디컴파일된 sub_140001440
을 살펴보면 _acrt_iob_func
함수를 통해 0번 스트림, 즉 stdin
파일 스트림을 가져온다
이것은 표준 입력을 하는 함수라는 의미이다
그리고 sub_140001440
안의 또다른 함수 sub_140001300
를 마저 살펴보면
_stdio_common_vfscanf
함수를 호출하는 것을 알 수 있다
따라서 sub_140001440
가 scanf
함수임을 확신할 수 있다
마찬가지로 main으로 다시 가서 scanf
로 함수 이름 변경
마지막으로 디컴파일된 sub_140001000
을 보면 입력받은 값을 1바이트 단위로 값을 비교하고 있다
즉 모든 문자열을 정해진 문자열과 비교하여 마지막으로 21번째 인덱스가 0이면 마침내 1을 리턴한다
다음과 같이 IDA에서 r 단축키를 사용해서 아스키 코드로 쉽게 변환할 수 있다
이 값들을 이어붙이면 flag가 나올 것이다
여기서 한 가지 주의할 점은 문자열의 끝은 NULL 문자로 0을 의미하는데 마지막에 비교하는 0은 직접 입력하지 않아도 자동으로 들어가게 된다
즉 Compar3_the_ch4ract3r
을 입력하면 Correct가 출력되고 이 값이 flag가 된다
🔑 DH{Compar3_the_ch4ract3r}
문제는 동일하다...
3문제나 같은 유형을 풀었으니 앞으론 혼자 잘 풀 수 있겠지,,,,?
마찬가지로 IDA로 파일을 열어준다
IDA가 찾아준 main
디컴파일된 main
이젠 printf와 scanf는 따로 분석안해도 될것같다
그런데 위의 문제들과는 다르게 이번엔 3중첩되어있어서 일단 캡처만 해왔다
sub_1400011B0
sub_140001080
*sub_140001060
sub_140001210
sub_1400010D0
*sub_140001070
sub_140001000을 분석해보면 12번동안 입력한 값과 특정 값을 1byte씩 비교해서 다르면 return .i64
, 즉 false
를 반환하고 같으면 return 1i64
, 즉 true
를 반환한다
그럼 이제 if ( *(_DWORD *)&aC[4 * i] != *(unsigned __int8 *)(a1 + i) )
를 해석해서 비교 하는 그 문자열이 무엇인지를 찾아야한다
aC 배열을 더블 클릭하니 배열값이 보였다
근데 아무래도 그 값이 flag 값인 것 같다
이렇게 간단하게 풀리는게 맞는진 모르겠다,,,,
시간될 때 다시 분석해봐야지! 꼭!,,,,
🔑 DH{Comp4re_the_arr4y}