abex crackme2를 풀 수 있는 방법은 정해져 있지 않다. 시리얼을 알아낼 수 있는 방법 정도로 풀 때, 비교할 시리얼이 어떻게 만들어지는지 핵심 루틴이 궁금했다. 시리얼이 어떻게 만들어지는지는 조금 분석 따라가기가 버겁다. 리버싱 핵심원리에서 읽었고, 읽어본 대로 책을 이후에 보지 않고 따라가 보았다. 버튼 이벤트 리스너 함수에서 내리다보면 Name 필드에 입력한 값을 복사하는 명령어가 있다. 그 아래에도 Name 필드의 값을 복사하고 VbaVarMove 함수를 호출한다. 아래에 자주 호출되는 VbaVarMove 함수는 무슨 내용인지 자세히 모르겠다. 조금 더 디버깅하면 VbaLenVar 이라는 함수가 나오는데 함수 호출 전에 4를 Local.53에 복사하는 것을 볼 수 있다. VbaLenVar은 문자열의 길이를 구하는 함수 같았다. 그대로 디버깅 해 따라가 보았다. VbaLenVar의 함수 모습 처음의 함수 프롤로그와 TlsGetValue 등의 함수를 출력하는 곳까지는 의미 없어 보인다. 사실 뭐 하는 내용인지 확실히는 모르겠다. 위의 캡처 사진에서 Eax에 있는 Name 필드의 값이 들은 주소를 스택에 한 번 더 넣고 내부에서 함수를 한 개 더 호출한다. 호출된 함수의 모습이다. 사실 잘 모른다고 했던 호출 부분들에서 이미 문자열의 길이를 구했었나보다. 유니코드로 된 문자열이 할당된 길이가 구해진? 위치는 Eax - 4였고, Eax에 그 값을 복사해 왔을 때 0xA였다. 그 다음에 오른쪽으로 1비트 쉬프트 연산으로 0x5가 되었고, 이는 유니코드의 문자열이 잡아먹는 길이가 2비트씩 되기 때문에 char 형 문자열 길이(실제 문자만의 길이)를 구하기 위해 shift 연산을 한 것 같다. abcde는 61 00 62 00 63 00 64 00 65 00으로 저장되어 있을 것이고, 차지하는 공간이 10인데 실제 문자열의 길이는 5니 1비트 쉬프트 연산을 해서 값의 1/2를 ...
리버싱 핵심원리 책을 읽으면서 실습했다. 크랙미란, 리버싱 연습을 위해 일부러 디버깅/리버싱으로 프로그램을 고의로 수정해서 문제를 풀어나가게 하는 프로그램들인데 유명한 입문? 크랙미 프로그램인 abex crackme 2를 리버싱 실습을 하려고 한다. abex2는 실행 시 이렇게 이름과 시리얼을 적는 곳과, Chcek, About, Quit 버튼이 세 개 있고 이름과 시리얼을 적고 check 버튼을 눌러서 이름에 대한 시리얼이 맞는 지 비교해 적절한 출력을 내 주는 프로그램이다. 이름에 1234를 적고 시리얼에 hello를 적어서 check 버튼을 눌렀더니 아니라고 뜬다. 그리고 이름이 4글자 미만이면 이름을 4글자 이상 적으라고 나온다. 이름은 최소 4글자는 적어야 한다. 올리디버거로 열어보았다. 이전에 보던 곳과는 다른 곳에서 시작한다. abex crackme 2는 비주얼 베이직으로 짜여있는 프로그램인데, 비주얼 베이직은 MSVBM이라는 비주얼 베이직 함수가 담겨있는 dll을 사용하고, 프로그램의 기본 main 함수가 아닌 버튼을 눌렀을 때 등의 버튼 이벤트 핸들러 함수 등에 사용자의 주요한 코드가 담겨있다고 한다. 실제로 ExeInfoPE로 살펴보았을 때 Visual Basic로 작성되어 있다는 것을 확인할 수 있었다. 버튼을 눌렀을 때의 이벤트 핸들러를 쉽게 찾기 위해 틀렸을 때 나오는 메시지박스의 문자열을 찾아보기로 했다. 올리디버거의 Search for - All referenced strings를 통해 프로그램에 있는 모든 문자열들을 찾아 볼 수 있다. 아래로 조금 내리니 틀렸을 때의 메시지와 맞췄을 때의 메시지 문자열을 다 찾아볼 수 있다. 더블클릭해서 주소를 찾아가 보았다. 문자열들을 집어넣어주고 CALL을 하는 모습이 보인다. 아래를 조금 내려보니 메시지박스를 띄우는 함수를 호출하는 것 같다. 이 부분에 브...
편의상 ButtonListner라는 레이블을 붙여보자. 주요 내용을 훑어보자. 함수 프롤로그는 대충 보고 GetDigItemTextA라는 함수를 호출하는 것이 보인다. 텍스트박스의 텍스트를 가져오는 함수인 것 같다. https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-getdlgitemtexta#parameters 대화 상자의 핸들러, 컨트롤러의 아이디?, 문자열을 입력받을 버퍼 위치, 버퍼의 크기 순 인자인것 같다. 스택에 들어가는 순으로 보면 eax가 가장 마지막 인자이고, 인자가 총 3개 들어가는 것을 보니 getDigItemTextA의 상위 함수 중 문자열 길이를 받지 않는 3개의 인자를 받는 함수를 사용한 듯 싶고, eax에 들어가는 주소가 문자열을 받아 저장하는 버퍼의 주소인 듯 싶다. 함수를 호출 후 eax에 들어있는 주소를 덤프 창에서 한번 확인 해 보자. 0019F6F4엔 아무것도 없다. 함수를 호출하고 나면, 메모리에 입력했던 123이 들어간 것을 볼 수 있고, 함수의 리턴값을 받아온 eax가 3의 값을 가지는 것을 볼 수 있다. 3은 문자열 길이로 추정된다. 여길 다시 보면, 함수를 호출하고 나와서 스택을 정리하지 않고 바로 실행문이 나오고, 이미 정리된 스택의 위치를 가리키는 esp스택의 4바이트 뒤에 다시 저장된 문자열의 주소가 나온다. 함수를 호출하고 난 뒤의 바로 다음 실행문은 비교를 위한 cmp문이다. esp + 5는 문자는 4바이트 뒤부터 시작하는 문자열의 2번째 문자로서 123에서 2를 가리키고 있다. '2'와 'a'를 비교하고 있다. jne 401135인데, 같지 않으면 점프한다. 점프된 곳을 따라가보자. Incorrect Password를 인자로 넣은 메시지 박스를 띄우고 리턴한다. 이 주소가 password를 검사하는 루틴에서 틀렸을 때 점...
댓글
댓글 쓰기