zj3t

email: euntaejang@gmail.com

Latest Posts
CodeEngn advance10 문제는 지금까지 푼 문제 중 가장 어려웠던 문제라고 생각됩니다.




프로그램을 실행하고 name과 serial 을 각각입력하고 나면 무수히 많은 함수가 존재하고, 이 무수히 많은 함수들에 들어가면 또 무수히 많은 함수, 또 무수히 많은 함수 한 세번 정도 중첩되 있는 것같다.. 우리는 연산을 하는 부분을 찾아야하는데 찾기가 굉장히 힘들다. 
따라서 중요한 부분의 함수들만 보면( 이 밑의 함수들도 굉장히 찾기 힘들다.)                                                                       

이 문자열은 어딘가 중요해 보인다.(나중에 연산에서 중요하게 쓰임!!!)


이 함수는 입력한 name과 serial을 소문자에서 대문자로 바꾸어 주는 함수이다. 
처음에 name을 대문자로 바꾸어 준후, 다른 명령을 실행하다 다시 호출되어 serial을 대문자로 변경한다.(우리는 serial이 대문자 이므로 name만 신경쓰면 된다.)

무수히 많은 함수들을 지나치면

첫번째 연산을 하는 함수를 발견할 수가 있다. 미리 말하자면 이 함수는 두번 호출되는데 처음에는 serial과 위의 이상한 문자열과의 연산을 하고, 두 번째는 name과 이상한 문자열과의 연산이 진행된다.                                                                                          

안으로 들어가보면 두개의 같은 함수가 호출 된다. 이는 연산 함수이다.

여기서 한번 더 함수에 들어가면...

연산 코드가 나온다.

즉 이 연산코드를 해석할 수 있으면 답을 찾을 수가 있다. 아까 보다 시키 연산코드 안으로 들어가면 첫번째, 두번째 연산코드가 있는데, 처음연산에서는                                     
                                  
AJXGRFV6BKOW3Y9TM4S2ZU                                                                            
I70H5Q81PDECLNAJXGRFV6BKOW3Y9TM4S2ZU                                                     
 I70H5Q81PDECLNAJXGRFV6BKOW3Y9TM4S2ZU                                                       I70H5Q81PDECLN            (이문자열은 이어져 있다. 공백을 포함)                                                                                
이 문자열에서 입력한 serial의 위치를 찾는다. 즉 12자리의 serial을 입력하고 그 serial이 WWWCCCJJJRRR 이라면 W와 AJGRF......을 byte단위로 CMP로 비교하여 문자열에서의 serial문자의 위치를 찾는다.    
             
 두번째 연산코드에서는 첫번째 위치가 아닌 문자열에 포함된 serial의 1byte문자의 두번째 위치를 찾는다. (처음에는 첫번 째 위치를 찾음) 예를 들어 serial의 1byte가 A라면 첫번째 연산에서는 위치가 0이므로 0이 반환되고(A가 문자열의 맨앞) 두번째 연산에서는 37을 반환 문자열은 한칸의 공백으로 연결되어 있기 때문이다.                                                       
이런식으로 serial의 대한 위치를 찾은뒤 또 많은 쓰레기 함수들을 지나치면 나오는 두번째 연산코드의 입구인 함수에서는 name에 대한 위치를 찾는다.                                         
sub EAX, EDX //EAX에는 serial의 두번째 위치값, EDX에는 name의 두번째 위치값이 포함
cmp EAX, 5 and jle xxxxxx //즉 위의 값을 뺀 결과가 5보다 작거나 같아야 성공구문으로 가게 된다.

답은 여러 개가 나올 수 있다. WWWCCCJJJRRR이므로 문자열에 포함된 W,C,J,R의 두번째 위치의 -5~+5의 값을 가진 것은 무수히 많기 때문이다. 따라서 위에 문제를 보면 0~9, a~z, A~Z의 순서라고 했으므로 답을 찾을 수가 있다.

3**6



       
                                                                              







F7로 무수히 많은 함수내부로 들어가서 실행하면 이러한 정답을 비교하는 구문을 찾을 수 있다. 중간에 name, password를 입력하는 부분뒤에도 더 들어가면 찾을 수가 있다.  



88228F는 10진수로 변경하면 8921743 이다. 여기서 정답이라 확신할 수 있는데 막상 실행하면 답이 아니라고 뜬다. 

프로그램을 실행하고 지금껏 EBX는 0으로 초기화 되어있었기 때문에, 무조건 실패로 분기되는 것이였다. 따라서 답은 8921743이 맞다.                                                                   

           

한 5~6시간 정도 앉아서 푼 문제였던거 같습니다. 노가다 성이 강했던거 같아요~~~






함수 내부부터는 한글 파일 첨부!!! 양도 너무 많고 프로그래밍으로 풀었기 때문에 한글파일로 첨부하겠습니다. 

-한글파일-
구글 블로그는 따로 파일첨부가 안되고 링크형식으로 되더라고요....




아무 serial을 입력했을 때의 뜨는 창!!



문자열 비교함수를 찾아 BP를 걸었다.

cmp함수를 호출하는 주소 내부로 들어가서 확인했더니 내가 입력한 값과 정답 serial을 비교하고 있는 것을 찾을 수가 있었다.                                                                               


정답!!!!!

여기까지는 저번 풀이과 같다. 저 마지막 jmp문이 OEP로가는 jmp문이였고 UPX뿐만 아니라 이 것도 이런 식으로 풀 수 있는 패킹이라는 것을 알게 되었다.

Ctrl+A를 눌러 패킹한 코드를 재 정렬한다.

그러면 보는 것처럼 패킹된 코드가 가지런히 나오게 된다.

문자열검색!!!

문자열 비교함수 밑 CMP에 BP를 걸고 실행!!


이렇게 하면 CodeEngn에 해당하는 serial값을 찾을 수가 있다.

저번 풀이와의 차이점은 ctrl+A로 코드를 재정렬해서 더 쉽고 정확하게 serial을 찾아내느냐 못찾아 내느냐인것 같다. 저번풀이를 이용하면 serial을 찾을 수는 있지만 강한 확신은 없는 것에 비해 이것은 입력한 serial과 문자열비교를 통해 보여주니 더 정확하게 알 수 있었다.

03번 문제와 같은 문제이다!!!

????
PEID로 확인해 보니 무엇이 처리된지 알 수 없다고 뜨더니 정상적인 코드가 아니다.

밑에 함수모음에서 문자열 비교함수를 찾아 BP를 걸고 실행!!!

name에 CodeEngn
serial에 아무 값이나 입력!!

serial값으로 의심되는 문자열이 딱 한번 등장한다. 확인 해보자!!

위에 값이 정답serial 이였다. 어떤 처리가 되었는지는 잘 모르겠다. 
더 확인해서 정확하게 알고 넘어가야 할 것 같다.





F9를 눌러 실행!!! name에 CodeEngn serial에 아무값이나 넣고 Check!!!!

문자열 비교함수로 내가 입력한 serial과 정답 serial을 비교!!

정말 쉬운문제였다!!!



 성공표시가 없기 때문에 입력부분을 찾아 BP를 걸었다.

loop부분이라 이 부분에 패스워드를 비교하는 구문이 있을것이라 생각했지만 아니였고 밑으로 내려봐도 패스워드를 비교하는 부분이 없었다.  그렇다면 함수 내부에 있다고 생각!!

이 call EDX 부분에서 프로그램이 종료되는 것을 알 수가 있었으므로 F7로 내부로 들어간다.



이부분이 입력한 password를 가져와서 정답 password와 비교하는 부분임을 연산하는 부분이다. 따라서 요약하자면 입력한 password를 한 byte씩 가져와서 43 52 41 41 41 43 4B 45 44 21와 비교한다. 즉 43 52 41 41 41 43 4B 45 44 21에 해당하는 것 이 정답이 된다. 
(아스키 코드로 변환!!!!)