no image
CodeEngn Advance 12
문제확인이번문제는 참 오래걸렸다. VB 특성상 MSVBVM60.DLL에 의하여 동작이 되기 때문에 개인적으로 다른 것에 비하여 분석하기가 까다로웠다. 풀이우선 시작부터 너무나 많이 왔다갔다하기때문에 중요한 부분만 사진으로 보겠다. 아래의 사진을 보면 ABCD를 입력하였을 경우 그에 해당하는 10진수의 값을 하나하나 주소에 적는 과정을 나타내고 있다. 이렇게 입력한 Name에 따라서 기록이 된다. 그렇게 입력된 값을 가지고 우리는 Value[5:9] 의 값이 밑에 rtcMidCharBstr에 의하여 4글자만 가지고 올 수 있게 된다. 밑에선 65666768에서 6768이 바로 그 값이 된다. 이 값은 나중에 시리얼에서 가운데 부분을 구성하게 된다. 위에서 나온 값을 가지고 아래의 부분에서 Loop가 진행이..
2015.07.22
no image
CodeEngn Advance 11
문제확인 확인 Name에 따른 시리얼이 형성되는 부분은 쉽게 찾을 수가 있다. 내가 입력한 name은 0000 serial은 11111111로 입력하였을때 아래와 같이 시러일이 비교되는 부분이 있다. 그리고 그 위에 이러한 키 값이 형성되는 부분이 존재 한다. 위에 있는 덤프창에 드래그 해 놓은 부분이 바로 키 값 형성에서 if 문을 결정짓게 해주는 요소들이다. 그리고 아래의 사진은 수많은 if문들이 존재한다. 실제로는 16~20개의 if 문이 존재한다. 하지만 여기서부터 문제가 시작되었다. 이번문제의 가장 큰 시사점은 작은 그림이 아니라 큰 그림을 보아야 한다는 것이다. 저러한 if문들을 계속 하나하나 따라가다보면 정말 미궁으로 빠져버린다. 본인은 미궁에서 2일을 소비했다...바로 위의 if문을 보는 ..
2015.07.17
no image
CodeEngn Advance 10
문제 확인 기초 확인 위의 사진은 주석과 같이 name을 입력 받고 name의 길이를 확인 하는 과정입니다. 이번에는 Serial을 입력받고 그 길이를 확인하는 과정입니다. 길이는 12글자여야 합니다. 참고로 이 접어놓은 부분은 문제의 의도를 잘못파악하고 단순노동을 작업하였다. 매우 삽질스러우니 한가할떄만 열어보자.키 값 형성 찾기우선 키 값이 어디선 형성되는지 찾기 위하여 정말로 많은 노가다를 하였다. 잘못 Step into하게 되어 헤매기를 얼마나 헤맸는지 결국 찾기는 하였다. 우선 계속 해서 우리는 Step Into를 통하여 안으로 들어갈 것이다.Step Into Step Into Step Into Step Into Step Into 드디어 키 값이 형성 되는 곳을 찾았다. 여기서 보아야 할 것은 ..
2015.07.13
no image
CodeEngn Advance 09
문제 확인문제를 확인해보면 참 설명이 간단하게 나와있다. Password는 무엇인가?이다. 그렇다면 시리얼값을 구하는 것일까했지만 여기서 문제는 우리가 직접 ID까지 알아내야한다는 것이다. 프로그램을 바로 실행시키면 아이디로 무엇을 입력해야할지 당황스럽다. 하지만 막상 디버거로 프로그램을 열면 바로 덤프 창에 This is the Username : DonaldDucK 이라고 적혀있는 것을 볼 수가 있다. 이것이 바로 우리의 ID 값이다. p.s 사실 굳이 이것을 발견하지 못해도 이후에 DonaldDuck과의 문자를 비교하는 Loop 구간이 있기에 처음에 발견하지 못하더라도 나중에 발견할 수가 있을 것이다. 풀이 우선 프로그램을 진행하다보면 위와 같이 내가 입력한 키값 123 (0x7B)와 실제 값인 0..
2015.07.12
no image
CodeEngn Advance 08
문제확인이번문제는 CodeEngn Basic에서도 유사한 문제가 존재한다. 하지만 Advance인 만큼 그때와는 다르게 열정적으로 풀었다. 정말 시간이 참 빨리가는 삽질을 한 것 같다. 우선 문제를 확인해보면 참 말은 쉽다. Key 값이 주어지고 그에 맞는 값을 찾아라. 여기서 힌트는 2자리라는 것이다. 하지만 정작 2자리를 입력하면 위와 같이 더 입력해야한다고 출력이 된다. 그러므로 우리는 CMP len(name),3을 비교하는 부분을 찾을 것이다. 그 부분은 밑에 사진에서와 같이 CMP EAX,3 의 형태로 있으며 숫자 3을 2로 수정하여 2자리로도 입력이 가능하게끔 패치를 해주자. 나는 저렇게 수정을 한 후에 OllyDump를 통해서 저장을 하였다. 이렇게 패치를 한 파일을 가지고 분석을 시작할 것..
2015.07.01
no image
CodeEngn Advance 06
문제확인우선 문제를 확인하면 이전에도 풀려고 했지만 결국 풀지 못했던 문제로 기억을 한다. 하지만 그 때에는 분명 리버싱을 처음 접했을때로 기억을 하기에 당시보다는 잘 풀 수 있겠지라는 자신감으로 리버싱을 시작하였다. 우선 UPX 패킹을 해제하고 리버싱을 계속 진행하면 된다. 풀이사실 이 문제는 정말 많이 삽질을 한것 같다. 출력되는 남은 군생활의 값을 증가시켜주는 부분을 찾았고 그 주위에서 CMP를 통한 비교문을 찾기 위하여 많은 노가다를 하였지만 결국 삽질도 여러번 하다가 문득 생각 난 것이 바로 치트엔진이였다. 사실 치트엔진을 통한 문제 풀이가 과연 리버싱에 도움이 되는 것인지는 모르겠지만 이참에 치트엔진 공부도 새롭게 같이 시작을 해보려한다. 우선 아래와 같이 치트엔진을 통하여 변화하는 값을 캐치..
2015.06.28
no image
CodeEngn Advance 05
문제확인이번 문제는 너무 설명 할 것도 없는 것같다. 풀이아래와 같이 vbaStrCmp를 찾으면 쉽게 시리얼을 찾을 수가 있다. Name에 따른 알고리즘 형성으로 인하여 키 값이 형성 되는 것이 아니라 그냥 시리얼 값을 찾는 것이기에 너무 간단히 끝나버렸다.
2015.06.28
no image
CodeEngn Advance 04
문제 확인 풀이 우선 위와 같이 lstrcmpA를 통하여 우리는 쉽게 해당 시리얼을 구할 수가 있지만 이렇게 문제풀이를 중심으로만 하면 실력향상에 차질이 있을 수도 있기에 직접 알고리즘을 분석하는 방법을 통하여 문제를 풀어보고자 한다. 위와 같이 알고리즘이 진행되는 부분을 표시해 놓았다. 위의 알고리즘을 커친 후 ESI의 값이 10진수로 시리얼의 가운데 값으로 자리잡고, EDI의 값은 16진수로 시리얼의 뒷자리 값으로 자리를 잡는다. 알고리즘에 대한 분석은 주석에 달아 놓은 것과 같고 직접해보는 것이 크게 도움이 될 것이다. 이제 알고리즘을 파악한 후 직접 키 값을 구하는 프로그램을 만들어보자. 위와 같이 나는 이렇게 Python을 통하여 키 값을 구하는 프로그램을 만들어 보았다. 이렇게 구한 값이 실제..
2015.06.28

문제확인


이번문제는 참 오래걸렸다. VB 특성상 MSVBVM60.DLL에 의하여 동작이 되기 때문에 개인적으로 다른 것에 비하여 분석하기가 까다로웠다. 





풀이


우선 시작부터 너무나 많이 왔다갔다하기때문에 중요한 부분만 사진으로 보겠다. 아래의 사진을 보면 ABCD를 입력하였을 경우 그에 해당하는 10진수의 값을 하나하나 주소에 적는 과정을 나타내고 있다. 이렇게 입력한 Name에 따라서 기록이 된다.


그렇게 입력된 값을 가지고 우리는 Value[5:9] 의 값이 밑에 rtcMidCharBstr에 의하여 4글자만 가지고 올 수 있게 된다. 밑에선 65666768에서 6768이 바로 그 값이 된다. 이 값은 나중에 시리얼에서 가운데 부분을 구성하게 된다.


위에서 나온 값을 가지고 아래의 부분에서 Loop가 진행이 된다. 한글자씩 가지고 연산을 하는 것이다. 이에 대한 설명은 예를 들어서 4949 일경우에 python으로 코드가 출력되게 한것이다.

자세히 보면 Loop후에 NEG EDX가 나오는데 이로 인하여 0-value를 하므로 인하여 우리가 원하는 값을 얻을 수가 있다.


그리고 이 밑에 부분이 가장 중요한 부분이라고 할 수 있다. 실제로 분석을 하다보면 너무 많은 분기문으로 인하여 지치게 된다. 그래서 저도 정말 많이 포기하고 싶었습니다.. 그래서 치트엔진, VB Decompiler, IDA 까지 동원하여 최대한 찾기위해 노력하였습니다. 

항상 어떤 중요한 변동이 있을떄마다 바로 이 부분을 지났기때문이다. 주석 또한 정말 위에도 강조하고 아래에서도 강조하게 된것은 한번만이 아니라 저 부분에서 핵심적으로 동작이 이루어지기 떄문이다.


이제 계속 실행을 하다보면 레지스터에 아래와 같이 정렬이 되며 E590는 위에서 연산을 통해 나온 가운데 시리얼 값이다.  추가적으로 실행하다보면 두번쨰 사진과 같이 한 글자가 사라지기도 하고 계속 이런식으로 변동이 이루어진다.


그리고 이 밑에 부분은 시리얼의 맨 앞자리 값을 결정 짓게해주는 부분이다. 어찌보면 가장 중요한 부분인데 fld fcom 등등 모르는 부분이 너무 많았다... 확실한 것은 저 부분에 들어가기 전에 모든 ECX에 5가 존재하고 그 5에 30을 더하여 EAX로 옮기는 것 같다. 


위를 통하여 14라는 숫자가 나온다. 거기에 6768-E590에서 맨 앞자리를 지우고 14를 앞에 붙여준다. 이렇게 해서 첫번째 시리얼 부분이 형성이 된 것이다. 참고로 여기서 5번째 글자를 없애면 된다.

그리고 마지막 부분의 시리얼 값은 맨 앞자리의 '1'의 10진수 값인 '49'가 나온다.

그리고 그 뒤에 0을 붙이고 맨 마지막 자리는 Len(name)+5의 값으로 형성이 된다.

이렇게 해서 ABCD일 경우의 Serial은 아래와 같다.

아래의 사진은 AAAA로 했을 경우의 성공문이다.



느낀점


이번 문제를 풀면서 정말 많은 자괴감에 빠져버렸다. 아무리 찾아도 찾아도 나오지가 않기에 리버싱이 내 적성이 아닌가 싶기도 느낄 정도였다. 이번문제의 답을 구하긴 했지만 이것도 완벽한 분석으로 구한 것이 아니다. 가운데 시리얼을 통해서 'od'라는 글자가 나왔을때 왠지 CodeEngn일거 같아서 한건데 성공해버렸다. 

그래서 다른 블로그를 참고하면서까지 이번문제를 풀었다. 정말 문제를 풀었으면 보통 기뻐야하는데 기분이 찝찝하다...다음엔 더 열공해서 풀 수 있길..ㅠㅠ


'Reversing > CodeEngn' 카테고리의 다른 글

CodeEngn Advance 15  (0) 2015.07.30
CodeEngn Advance 14  (0) 2015.07.24
CodeEngn Advance 11  (0) 2015.07.17
CodeEngn Advance 10  (0) 2015.07.13
CodeEngn Advance 09  (0) 2015.07.12

문제확인





확인




Name에 따른 시리얼이 형성되는 부분은 쉽게 찾을 수가 있다. 내가 입력한 name은 0000 serial은 11111111로 입력하였을때 아래와 같이 시러일이 비교되는 부분이 있다. 그리고 그 위에 이러한 키 값이 형성되는 부분이 존재 한다. 



위에 있는 덤프창에 드래그 해 놓은 부분이 바로 키 값 형성에서 if 문을 결정짓게 해주는 요소들이다. 그리고 아래의 사진은 수많은 if문들이 존재한다. 실제로는 16~20개의 if 문이 존재한다. 하지만 여기서부터 문제가 시작되었다. 

이번문제의 가장 큰 시사점은 작은 그림이 아니라 큰 그림을 보아야 한다는 것이다. 저러한 if문들을 계속 하나하나 따라가다보면 정말 미궁으로 빠져버린다. 본인은 미궁에서 2일을 소비했다...

바로 위의 if문을 보는 것이 아니라 아래와 같이 Dump를 지속적으로 확인해주어야 한다. 402538의 부분을 보면서 계속 진행을 하다보면 아래와 같이 3B10  31  6D  64  38 이 존재하고 있는 것을 확인 할 수가 있다. 여기서 31은 내가 입력한 serial인 ('1111')의 한 글자이다. 


위와 같이 셋팅이 된후에는 바로 연산이 진행된다. 3B10  +  31*(64+38)과 같은 식으로 진행이 된다. 그렇게 나온 값이 Sum = CF1BC이다. 이제 이와같이 이러한 연산이 key[]에 있는 모든 배열들을 순차적으로 더할 때까지 반복이 된다.

그렇게 해서 나온 값이 바로 sum = 3315C0이다. 이제 이 값을 가지고 다른 연산이 진행이 된다. 바로 F로 나누는 것이다.


F로 나눈 후에 3315C0 / F = 367D9 ... 9가 남는다.

이제 이 9에 0x30을 더 해준 후에 키 값으로 올려버린다.

그리고 남아있던 367D9에는 2를 곱하여 준다.

이렇게 더이상 F로 나누어 질 수 없을 때 까지 반복이 된다.

하지만 계속 반복이 되는 중에 만약 나머지가 0x3A~0x40일 경 밑에 2번쨰 처럼 '0~9,A~Z'가 아닌 특수문자가 나오게 되는데 이를 방지하기 위하여 A~E가 나머지로 나올 경우 +8을 해준다.


이렇게 계속 반복을 하다가 더이상 F로 나눌 수 없는 값이 될때까지 반복을 한 후에 마지막 나머지 또한 key값으로 보낸다.

위에 말이 너무 복잡하게 설명이 되어있는데 코드로 본다면 아래와 같이 간결하게 나열이 된다.




풀이


위에서 구한 방법을 통하여 94E7DB1B를 뒤에서 부터 다시 올라오면 된다. 그렇게 되면 D2A734이 나오는데 이는 맨 처음의 SUM 값인 0X3B10이 더해져있는 값이다. 따라서 KEY[]를 구하는 방법은 KEY[] = (D2A734 - 3B10) / 426C 이다. 이제 이렇게 나온 값은 0x32B이며 KEY[]의 모든 ASCII의 조합이 이렇게 나오면 된다는 것이다.

정답은 많은 경우의 수가 존재하므로 그 중에서 하나를 골라서 게시판에 비공개로 올리면 정답으로 처리가 될 것이다.


'Reversing > CodeEngn' 카테고리의 다른 글

CodeEngn Advance 14  (0) 2015.07.24
CodeEngn Advance 12  (1) 2015.07.22
CodeEngn Advance 10  (0) 2015.07.13
CodeEngn Advance 09  (0) 2015.07.12
CodeEngn Advance 08  (50) 2015.07.01

제 확인







기초 확인



위의 사진은 주석과 같이 name을 입력 받고 name의 길이를 확인 하는 과정입니다.


이번에는 Serial을 입력받고 그 길이를 확인하는 과정입니다. 길이는 12글자여야 합니다.


참고로 이 접어놓은 부분은 문제의 의도를 잘못파악하고 단순노동을 작업하였다. 매우 삽질스러우니 한가할떄만 열어보자.



분석


IDA를 통하여 HEX-Ray 기능을 통하여 성공 구문이 있는 곳을 확인 하였을때, 아래와 같이 check_serial 이라는 부분이 있는 것을 확인 할 수가 있다. 정말 누가 봐도 저곳을 확인해달라는 말인 것을 알 수가 있다.


Check_Serial() 내부로 들어오면 아래와 같이 확인을 할 수가 있는데, 여기서 확인을 해야 할 것은 붉게 표시한 3곳을 잘 보아야한다. stringFindSecond 함수를 두번 호출하고 그 반환 값들의 차를 구하여 그 값이 5가 넘지 않을 경우에 v28 에 0을 준다는 것이다. 이게 구체적으로 어떻게 생각해야 하는지는 아래에서 설명하겠다.


위의 부분이 바로 ida를 통하여 붉게 표시했던 3곳이다. 여기서 보아야 할 것은 첫번쨰 함수를 호출하기 전에 내가 입력한 serial 값의 한글자를 가져오는 작업이 이루어졌고, 두번째 호출을 하기 전에는 입력한 Name의 한글자를 가져오는 것을 확인 할 수가 있었다. 아래의 사진과 같이 설명을 하겠다.

만약 Name = 1111  serial = 000000000000 일경우를 생각해보자. 여기서 위의 순서대로 우선 serial 한글자인 0을 가지고 온다. 이 0을 첫번째 strFindSecond()를 통하여 호출을 하였을 경우 아래에 있는 키 순서값들중에서 0이 나올때까지 계속해서 한글자씩을 보낸다. 25번째에 '0'이라는 값이 있다. 

이번엔 두번쨰 호출에서 name의 한글자인 1을 생각해보자. 1의 경우는 30번쨰에 위치를 하고 있다. 이 둘의 범위는 5를 초과하지 않으므로 성공문이 출력이 된다. 이처럼 결국 name 1을 기준으로 한다면 '1'이 30번쨰이니 25~35번째 까지의 모든 단어가 성공문을 출력할 수 있게 해준다. 이것이 바로 CMP EAX, 5를 확인하는 이유이다. 

이제 키 값이 어떻게 형성되는지 확인 했으니 프로그래밍을 해보자.

'A.J.X.G.R.F.V.6.B.K.O.W.3.Y.9.T.M.4.S.2.Z.U. .I.7.0.H.5.Q.8.1.P.D.E.C.L.N'



프로그래밍



코드에 대한 설명은 주석에 구체적으로 해놓았다.


참고로 여기서 출력 되는 J - 'A'의 경우 위에 주석에서는 써놓았지만 a-z를 하면 소문자로 치환하고 해서 번거로우므로 그냥 대문자 자체로 출력되도록 하였다. 따라서 저기서 'A'는 'a'라고 생각하면 된다.

p.s 2일에 걸쳐서 삽질을하여 풀었다가, 우연히 카페에서 이 문제를 다시보는데 문득 생각이 들어서 풀 수가 있었다. 고로 리버싱문제는 인내를 갖고 여러 방면으로 생각을 해봐야 문제를 쉽게 풀 수 있을 것 같다.

10_Find_Key.py


'Reversing > CodeEngn' 카테고리의 다른 글

CodeEngn Advance 12  (1) 2015.07.22
CodeEngn Advance 11  (0) 2015.07.17
CodeEngn Advance 09  (0) 2015.07.12
CodeEngn Advance 08  (50) 2015.07.01
CodeEngn Advance 06  (0) 2015.06.28

문제 확인


문제를 확인해보면 참 설명이 간단하게 나와있다. Password는 무엇인가?이다. 그렇다면 시리얼값을 구하는 것일까했지만 여기서 문제는 우리가 직접 ID까지 알아내야한다는 것이다. 프로그램을 바로 실행시키면 아이디로 무엇을 입력해야할지 당황스럽다. 


하지만 막상 디버거로 프로그램을 열면 바로 덤프 창에 This is the Username : DonaldDucK 이라고 적혀있는 것을 볼 수가 있다. 이것이 바로 우리의 ID 값이다. p.s 사실 굳이 이것을 발견하지 못해도 이후에 DonaldDuck과의 문자를 비교하는 Loop 구간이 있기에 처음에 발견하지 못하더라도 나중에 발견할 수가 있을 것이다.




풀이



우선 프로그램을 진행하다보면 위와 같이 내가 입력한 키값 123 (0x7B)와 실제 값인 0x88228F를 비교하는 것을 확인 할 수가 이다. 그리고 조금 더 밑에는 주석에서와 같이 DonaldDuck인지를 비교하는 Loop 구간을 확인 할 수가 있다.

키 값을 알았지만 자꾸 실패문이 뜨는 것을 확인 할 수가 있었다. 이는 성공문을 출력하기 위해서는 우리가 패치를 해야한다는 것이다. 이러한 패치는 2가지 과정으로 이루어 질 것이다. 성공구문 근처에서 틀린 키값을 가지고 수정을 하는 과정과 옳은 키 값을 가지고 수정을 하는 과정이다. 


이와 같이 틀린 키 값을 가지고 프로그램을 진행하기 위해서는 2번의 명령어를 수정해야한다. 이를 통하여 우리는 틀린 키 값으로도 성공문을 확인 할 수가 있게 되었다. 


이번에는 옳은 키값을 가지고 수정을 하였다. 이번에는 한가지의 명령어만 수정을 하면 되었다. 그렇다는 것은 바로 저 부분만 고치면 옳은 키값을 넣을 경우에는 성공문으로 가게 되고 틀린 키 값을 넣으면 실패문이 출력되도록 할 수가 있다.




키 값 찾기



CMP EAX, PTR DS:[ECX] 에서 EAX에는 우리가 입력한 값이 전달되고 PTR 부분에 키 값이 저장되어 있다. 하지만 이 PTR의 주소는 실행을 할 때마다 다른곳에 위치하고 있다는 것을 확인 할 수가 있었다. 그렇다면 이는 어떠한 것 떄문에 그런지 확인을 해보자.


바로 위의 사진에서와 보듯이 우리는 MOV DWORD PTR DS:[BC4404],EAX를 통하여 BC4404의 주소에 키 값이 저장된 공간의 위치가 전달 되는 것을 확인 할 수가 있다. 이러한 키 값이 있는 곳의 주소는 VirtualAlloc 를 통하여 형성이 된다.  VirtualAlloc를 통하여 할당된 주소를 EAX에 반환하고 그 값에 ADD EAX,2A0를 통하여 최종적으로 전달할 공간의 주소를 형성한다.


위의 사진을 보자. Address 파라미터의 값이 NULL일 경우 시스템이 주소를 결정한다는 것이다. 바로 이것이 키 값이 저장된 위치가 실행할때마다 변화했던 이유이다.


앞에서 확인 했던 것과 같이 키 값이 있는 곳의 주소는 00BC4404에 기록이 된다. 저 해당 주소로 가면 우리가 성공문을 출력하는데 필요한 키 값이 위치하여 있다. 추가적으로 아래의 사진은 이번 문제를 삽질할때 보았던 Flag Register에 관해 짧게 써있는 것이다. 


'Reversing > CodeEngn' 카테고리의 다른 글

CodeEngn Advance 11  (0) 2015.07.17
CodeEngn Advance 10  (0) 2015.07.13
CodeEngn Advance 08  (50) 2015.07.01
CodeEngn Advance 06  (0) 2015.06.28
CodeEngn Advance 05  (0) 2015.06.28

문제확인


이번문제는 CodeEngn Basic에서도 유사한 문제가 존재한다. 하지만 Advance인 만큼 그때와는 다르게 열정적으로 풀었다. 정말 시간이 참 빨리가는 삽질을 한 것 같다. 우선 문제를 확인해보면 참 말은 쉽다. Key 값이 주어지고 그에 맞는 값을 찾아라. 여기서 힌트는 2자리라는 것이다.


하지만 정작 2자리를 입력하면 위와 같이 더 입력해야한다고 출력이 된다. 그러므로 우리는 CMP len(name),3을 비교하는 부분을 찾을 것이다. 그 부분은 밑에 사진에서와 같이       CMP EAX,3 의 형태로 있으며 숫자 3을 2로 수정하여 2자리로도 입력이 가능하게끔 패치를 해주자. 나는 저렇게 수정을 한 후에 OllyDump를 통해서 저장을 하였다.


이렇게 패치를 한 파일을 가지고 분석을 시작할 것이다. 일단 Name 값은 AA로 시작을 하였다.

진행을 하다보면 위와 같이 성공으로 가는 분기문이 나타나며 레지스터 부분을 보면 내가 입력한 값과 해당 name에 따른 key 값이 나타나 비교될려 하는 것을 확인 할 수가 있다. 따라서 우리는 이처럼 쉽게 key 값을 확인 할 수가 있다. 문제는 key 값이 주어져 있고 우리는 name을 찾아야 한다는 것이다. 

그러므로 우리가 해야할 것은 바로 알고리즘 분석이다. 참고로 이 알고리즘 분석에서 애를 꽤 많이 먹었다. 결국 5개의 알고리즘에서 한개는 끝까지 풀지 못하였다. 하지만 그렇다 해도 문제를 푸는데에 있어서는 지장이 없다.



알고리즘 분석



첫번째 알고리즘이다. 위의 주석과 같이 name[i]를 통한 연산이 진행된 후에 레지스터를 보는 것과 같이 ESI에 저장되어있는 값의 앞자리 4자리가 첫번째부분의 키 값으로 사용이 된다. 이처럼 첫번째 알고리즘은 쉽게 분석을 하여 끝낼 수가 있다.


두번째 알고리즘이다. 이번에도 위와 같이 쉬운 연산으로 진행이 되지만 가령 Name이 'AB'일 경우 뒷자리인 'B'에서부터 연산을 시작한다. 뿐만 아니라 여기서는 Local.4가 있는 것을 확인 할 수가 있는데, 연산을 통한 값이 바로 이 Local.4에 저장이 되어 나중에 최종 키 완성에 전달이 된다. 이 값이 두번째 키 값이 된다.


세번째 알고리즘이다. 이 부분도 주석과 같이 쉽게 설명이 되어 있고 레지스터에서 보는 것과 같이 EDI의 앞자리 4자리가 키값의 4번째 값에 쓰인다.


네번째 알고리즘이다. 이 부분은 괜히 쓸때 없이 길다. EBX의 값이 마지막 키 값으로 사용이 된다. 



삽질 - 실패


위에서 확인 한 것과 같이 4개의 알고리즘을 통해 Key1 - Key2 - 빈부분 - Key3 - Key4 로 진행이 되어 있는 것을 확인 할 수가 있다. 그렇다 바로 저 빈부분이 내가 정말 삽질을 해도 나의 실력으로는 더이상 하지 못할 그것이였다. 분석하면서도 너무 복잡하여 결국 포기하여 버렸다.

위와 같이 FILD 부분과 RETN의 두칸 위에인 FISTP Cases 9,A,B....이 부분을 통해서 FILD에서 읽을 부분을 FISTP에서는 저장할 공간을 나타내어 값을 옮기는 형식으로 진행이 되는 것 같다. 이를 통해서 덤프창에서와 같이 가운데 키 값의 값이 형성이 된다. 이 키 값은 결국 밑의 연산을 통해서 나타난다.


위와 같이 ADD 연산을 통해서 덤프창에 있는 PTR:EAX의 값에 EDX를 더하므로 인하여 밑에와 같이 키 값이 형성이 된다. 이 키 값을 통하여 위의 사진처럼 FILD를 통하여 키 값이 형성이 된다. ...내가 말했지만 참 모르겠다. 정말 이 부분은 내 멘탈이 찢겨진 곳이라 할 수 있다.




프로그래밍


위의 알고리즘들을 통하여 우리는 프로그램을 만들 수가 있다. 브루트포스와 같이 모든 값을 출력하는 형식으로 프로그래밍을 해보았다. 여기서 내가 잊지 않기 위한 필기로서 파이썬에선 배열을 선언하고자 할 때 tmp=[0]*n 을 통하여 해당 크기 만큼의 값을 선언을 해 놓아야 한다. 그리고 아래의 5~7번줄과 같이 값을 선언해주면 된다.

위와 같이 코드를 짜준 다음에 실행을 하면 아래와 같이 텍스트파일이 생성이 되어있다. 이를 통하여 우리는 모든 경우의 값을 확인 할 수가 있으며, 주어진 문제의 키값을 통하여 Ctrl+F를 통하여 찾으면 문제를 풀 수가 있다. 


텍스트파일에서 찾은 값을 통하여 입력을 해주어 답이 맞는지를 확인하는 과정이다. 솔직히 쉽게 풀 수 있었는데, 모든 알고리즘을 분석하려다 보니 시간이 오래걸려 버렸다. 그리고 아래의 코드는 위와 같이 할 수 있는 알고리즘을 모두 출력하는 것이 아니라 입력한 키 값에 해당하는 부분을 출력해주는 프로그램을 별도로 만들어 보았다. 

아무래도 위의 프로그램보단 아래의 프로그램이 문제를 푸는데에는 시간이 훨씬 절약이 된다. 이렇게 코드를 짜 놓으면 주어진 문제의 Name 값이 길어지더라도 쉽게 문제를 풀 수가 있을 것이다. 

아래의 사진은 위의 프로그램을 통하여 답을 찾은 결과이다. 새삼스럽지만 답은 블럭처리하였다. 글을 읽는 여러분도 쉽게 문제를 풀 수가 있을 것이다. 나처럼 저 늪에 빠지지 않는다면..

by Kali-KM


'Reversing > CodeEngn' 카테고리의 다른 글

CodeEngn Advance 10  (0) 2015.07.13
CodeEngn Advance 09  (0) 2015.07.12
CodeEngn Advance 06  (0) 2015.06.28
CodeEngn Advance 05  (0) 2015.06.28
CodeEngn Advance 04  (0) 2015.06.28

문제확인


우선 문제를 확인하면 이전에도 풀려고 했지만 결국 풀지 못했던 문제로 기억을 한다. 하지만 그 때에는 분명 리버싱을 처음 접했을때로 기억을 하기에 당시보다는 잘 풀 수 있겠지라는 자신감으로 리버싱을 시작하였다. 

우선 UPX 패킹을 해제하고 리버싱을 계속 진행하면 된다.




풀이


사실 이 문제는 정말 많이 삽질을 한것 같다. 출력되는 남은 군생활의 값을 증가시켜주는 부분을 찾았고 그 주위에서 CMP를 통한 비교문을 찾기 위하여 많은 노가다를 하였지만 결국 삽질도 여러번 하다가 문득 생각 난 것이 바로 치트엔진이였다. 

사실 치트엔진을 통한 문제 풀이가 과연 리버싱에 도움이 되는 것인지는 모르겠지만 이참에 치트엔진 공부도 새롭게 같이 시작을 해보려한다. 우선 아래와 같이 치트엔진을 통하여 변화하는 값을 캐치한다.

위의 사진과 같이 치트엔진을 통하여 우선 해당 N번째의 값인 10을 입력해주고 그 다음은 Increased value를 통하여 두개의 값만 남았다. 여기서 첫번째 주소로 이동을 하여 확인을 해볼 것이다. 주소는 02583DB0로 이동을 한다. 그러면 위의 덤프창에서와 같이 0xA의 값이 존재하는 것을 확인 할 수가 있다.


위의 사진과 같이 해당 덤프에 BP를 건다. 위와 같이 ON ACCESS를 하는 것이 적당할 것이다. 그 후 BP를 통하여 계속 진행을 하다보면 아래와 같은 지점이 나타난다. 이 지점에서 우리가 현재 N번쨰인 B와 316을 비교를 한다. 이를 통해 우리는 남은 군 생활 수가 0x316 일수도 있다는 것을 확인 할 수가 있다. 이제 확인을 위하여 명령어를 바꾸어 보자.


0x316보다 클 경우에는 해당지점으로 점프를 한다. 그렇다면 우리는 확인을 위하여 JL을 JMP로 바꾸어 볼 것이다. 아래와 같이 바꾼 후에 진행을 할 경우 결국 RETN 8을 끝으로 프로세스가 종료 되는 것을 확인 할 수가 있다.

이러한 작업을 통하여 우리가 찾은 비교문이 올바른 지점이라는 것을 확인 할 수가 있었다. 이러한 방법을 통하여 문제를 풀 수가 있다. 치트엔진을 이용해서 더 쉽게 풀 수가 있었던 것 같다. 하지만 치트엔진보다 더 쉬운 방법이 있는데 바로 아래와 같은 디컴파일러를 이용하는 것이다. 디컴파일러를 이용하면 바로 1 TO 790(0x316)을 확인 할 수가 있다. 하지만 이는 실력 향상에는 안좋을 것 같다. 이러한 방법이 있다는 것만 잊지 말자.


'Reversing > CodeEngn' 카테고리의 다른 글

CodeEngn Advance 09  (0) 2015.07.12
CodeEngn Advance 08  (50) 2015.07.01
CodeEngn Advance 05  (0) 2015.06.28
CodeEngn Advance 04  (0) 2015.06.28
CodeEngn Advance 03  (0) 2015.06.28

문제확인


이번 문제는 너무 설명 할 것도 없는 것같다.




풀이


아래와 같이 vbaStrCmp를 찾으면 쉽게 시리얼을 찾을 수가 있다. Name에 따른 알고리즘 형성으로 인하여 키 값이 형성 되는 것이 아니라 그냥 시리얼 값을 찾는 것이기에 너무 간단히 끝나버렸다.



'Reversing > CodeEngn' 카테고리의 다른 글

CodeEngn Advance 08  (50) 2015.07.01
CodeEngn Advance 06  (0) 2015.06.28
CodeEngn Advance 04  (0) 2015.06.28
CodeEngn Advance 03  (0) 2015.06.28
CodeEngn Advance 01  (0) 2015.06.27

문제 확인





풀이



우선 위와 같이 lstrcmpA를 통하여 우리는 쉽게 해당 시리얼을 구할 수가 있지만 이렇게 문제풀이를 중심으로만 하면 실력향상에 차질이 있을 수도 있기에 직접 알고리즘을 분석하는 방법을 통하여 문제를 풀어보고자 한다. 


위와 같이 알고리즘이 진행되는 부분을 표시해 놓았다. 위의 알고리즘을 커친 후 ESI의 값이 10진수로 시리얼의 가운데 값으로 자리잡고, EDI의 값은 16진수로 시리얼의 뒷자리 값으로 자리를 잡는다. 알고리즘에 대한 분석은 주석에 달아 놓은 것과 같고 직접해보는 것이 크게 도움이 될 것이다. 이제 알고리즘을 파악한 후 직접 키 값을 구하는 프로그램을 만들어보자.


위와 같이 나는 이렇게 Python을 통하여 키 값을 구하는 프로그램을 만들어 보았다. 이렇게 구한 값이 실제 프로그램과 동일한 결과를 도출해내는지를 확인하기 위하여 아래와 같이 확인을 할 수가 있다.



'Reversing > CodeEngn' 카테고리의 다른 글

CodeEngn Advance 06  (0) 2015.06.28
CodeEngn Advance 05  (0) 2015.06.28
CodeEngn Advance 03  (0) 2015.06.28
CodeEngn Advance 01  (0) 2015.06.27
CodeEngn Basic 20  (0) 2015.06.04