국내에서 리버싱을 배울 수 있는 곳은 정말 한정적이다.
그나마 http://reversing.kr/ , https://dreamhack.io이며, 이외에는 영문으로 검색해야 찾아볼 수 있다.
Reversing.Kr
This site tests your ability to Cracking & Reverse Code Engineering. Now Challenge a problem for each environment. (Windows, Linux, .Net, Flash, Java, Python, Mobile..) Admin E-Mail: gogil@reversing.kr
reversing.kr
해커들의 놀이터, Dreamhack
해킹과 보안에 대한 공부를 하고 싶은 학생, 안전한 코드를 작성하고 싶은 개발자, 보안 지식과 실력을 업그레이드 시키고 싶은 보안 전문가까지 함께 공부하고 연습하며 지식을 나누고 실력 향
dreamhack.io
리버싱. kr에서는 기초적인 공부를 하고 난 뒤 직접 풀어봐야 알 수 있고 아무것도 모르고 시직 할 때는 드림핵에서 공부하는 걸 추천한다.
아무튼 오늘 풀어볼 문제는 드림핵에 rev_basic #1 첫 번째 문제다.
문제를 다운로드하고 ida로 가지고 오면 아래와 같은 상태일 것이다.
어떠한 값을 입력하면 "Correct" , 아니라면 "Wrong"을 출력한다.
IDA의 디버거를 이용해서 입력을 할 수 있지만 윈도우의 명령 프롬포트(CMD)에 chall.exe 파일을 드래그해서 가지고 오면 이 방식으로도 디버깅이 가능하다.
아직 문제의 답을 모르기 때문에 아무리 입력해도 "Wrong"으로 출력이 될 것이기에 한번 파해쳐 볼 것이다.
함수창에 main으로 쓰여있는 함수를 클릭하면 나오는 코드이자, 기본 코드 이기도 하다.
; int __cdecl main(int argc, const char **argv, const char **envp)
main proc near
var_118= byte ptr -118h
var_18= qword ptr -18h
; __unwind { // __GSHandlerCheck
push rdi
sub rsp, 130h
mov rax, cs:__security_cookie
xor rax, rsp
mov [rsp+138h+var_18], rax
lea rax, [rsp+138h+var_118]
mov rdi, rax
xor eax, eax
mov ecx, 100h
rep stosb
lea rcx, aInput ; "Input : "
call sub_1400013E0
lea rdx, [rsp+138h+var_118]
lea rcx, a256s ; "%256s"
call sub_140001440
lea rcx, [rsp+138h+var_118]
call sub_140001000
test eax, eax
jz short loc_1400013B6
하지만 여기서 알아야 할 정보는 F5를 눌러야 더 자세히 나온다.
그 정보 값은 어셈블리어 위에 있는 " ; __unwind { // __GSHandlerCheck " 코드다.
눌러봤다면 화면창은 이럴 것이다.
int __cdecl main(int argc, const char **argv, const char **envp)
{
char v4[256]; // [rsp+20h] [rbp-118h] BYREF
memset(v4, 0, sizeof(v4));
sub_1400013E0("Input : ", argv, envp);
sub_140001440("%256s", v4);
if ( (unsigned int)sub_140001000(v4) )
puts("Correct");
else
puts("Wrong");
return 0;
}
코드가 아까보다 단순해졌고 한눈에 보기 쉬워졌다.
자세히 보면 if문에 sub_140001000이 같이 있다. 이 함수는 전에 올렸던 글에도 봤었던 중요 함수라 말한 적이 있다.
그렇다면 해당 함수로 더 자세히 들어가 보도록 하자
_BOOL8 __fastcall sub_140001000(_BYTE *a1)
{
if ( *a1 != 67 )
return 0i64;
if ( a1[1] != 111 )
return 0i64;
if ( a1[2] != 109 )
return 0i64;
if ( a1[3] != 112 )
return 0i64;
if ( a1[4] != 97 )
return 0i64;
if ( a1[5] != 114 )
return 0i64;
if ( a1[6] != 51 )
return 0i64;
if ( a1[7] != 95 )
return 0i64;
if ( a1[8] != 116 )
return 0i64;
if ( a1[9] != 104 )
return 0i64;
if ( a1[10] != 101 )
return 0i64;
if ( a1[11] != 95 )
return 0i64;
if ( a1[12] != 99 )
return 0i64;
if ( a1[13] != 104 )
return 0i64;
if ( a1[14] != 52 )
return 0i64;
if ( a1[15] != 114 )
return 0i64;
if ( a1[16] != 97 )
return 0i64;
if ( a1[17] != 99 )
return 0i64;
if ( a1[18] != 116 )
return 0i64;
if ( a1[19] != 51 )
return 0i64;
if ( a1[20] == 114 )
return a1[21] == 0;
return 0i64;
}
이제 뭔가 알듯 말 듯 한 코드의 형태가 나왔다.
한번 클릭해 보니 해당 값은 int, 즉 정수값인데 ida에서는 값을 변환을 시킬 수 있기에 한번 char인 문자값으로 바꿔보면 어떠한 결과가 나올까?
단축키 혹은 우클릭으로 해당 값을 변환시킬 수 있으니 참고하길 바란다.
변환한 코드
_BOOL8 __fastcall sub_140001000(_BYTE *a1)
{
if ( *a1 != 'C' )
return 0i64;
if ( a1[1] != 'o' )
return 0i64;
if ( a1[2] != 'm' )
return 0i64;
if ( a1[3] != 'p' )
return 0i64;
if ( a1[4] != 'a' )
return 0i64;
if ( a1[5] != 'r' )
return 0i64;
if ( a1[6] != '3' )
return 0i64;
if ( a1[7] != '_' )
return 0i64;
if ( a1[8] != 't' )
return 0i64;
if ( a1[9] != 'h' )
return 0i64;
if ( a1[10] != 'e' )
return 0i64;
if ( a1[11] != '_' )
return 0i64;
if ( a1[12] != 'c' )
return 0i64;
if ( a1[13] != 'h' )
return 0i64;
if ( a1[14] != '4' )
return 0i64;
if ( a1[15] != 'r' )
return 0i64;
if ( a1[16] != 'a' )
return 0i64;
if ( a1[17] != 'c' )
return 0i64;
if ( a1[18] != 't' )
return 0i64;
if ( a1[19] != '3' )
return 0i64;
if ( a1[20] == 'r' )
return a1[21] == 0;
return 0i64;
해당 문자값을 모아보자면 "Compar3_the_ch4ract3r" 이고 이 값을 input에 넣어보면
Correct로 정답을 맞출 수 있다.
'Security > Reverse Engineering' 카테고리의 다른 글
리버스 엔지니어링, 밑 바닥부터 시작하기 (5) (0) | 2024.04.13 |
---|---|
리버스 엔지니어링, 밑 바닥부터 시작하기 (4) (2) | 2023.11.01 |
리버스 엔지니어링, 밑 바닥부터 시작하기 (3) (2) | 2023.10.28 |
리버스 엔지니어링, 밑 바닥부터 시작하기 (2) (2) | 2023.10.28 |
리버스 엔지니어링, 밑 바닥부터 시작하기 (2) | 2023.10.25 |