본문 바로가기

[Riversing]/[코드엔진] BASIC

[코드엔진] basic7

코드엔진 사이트에 들어가 basic7 문제를 다운로드 받고 압축을 푼다(비밀번호 : codeengn)

 

우선 Exeinfo PE로 파일을 확인해보자.

 

패킹은 되어있지 않으니 olldbg로 정확한 분석 ㄱ

 

를 하기전에 프로그램을 실행시켜 보면

시리얼 넘버를 입력받아 맞으면 통과 아니면 에러인 단순한 프로그램 인 것 같다.

진짜로 ollydbg로 정확한 분석 ㄱㄱ

 

Text Strings 를 확인해보면 에러, 통과 분기점과 시리얼 넘버처럼 보이는 숫자들이 보인다.

 

이동해서 확인해보자.

 

여러 함수들이 보인다.

정리해보자.

 

(더보기를 눌러주세용 (__) )

 

-(0040106C ~ 00401078) GetDIgItemTextA

더보기

UINT WINAPI GetDlgItemText(

  _In_   HWND hDlg,

  _In_   int nIDDlgItem,

  _Out_  LPTSTR lpString,           /* 입력받은 텍스트를 저장하는 부분 */

  _In_   int nMaxCount

);

 

대화상자에서 텍스트에 관한 정보를 얻는 함수인 GetDlgItemText 를 이용해서 사용자가 입력한 시리얼에 대한 정보를 얻고있는 부분. 어셈블리어 코드를 통해서 보면 아래와 같이 입력되어 있다.

 

0040106C PUSH 25 Count=25 (37.) nMaxCount
0040106E PUSH 07.00402324 Buffer=07.00402324 IpString
00401073 PUSH 68 ControlID=68 (104.) nIDDIgItem
00401075 PUSH DWORD PTR SS:[EBP+8] hWnd hDlg
00401078 CALL <JMP.&USER32.GetDlgItemTextA> GetDIgItemTextA  GetDIgltemText

=> 우리가 시리얼 입력칸에 입력한 값이 07.00402324 주소에 저장된다.

 

-(0040107D ~ 00401099) GetVolumeInformationA

더보기

BOOL WINAPI GetVolumeInformation(

  _In_opt_   LPCTSTR lpRootPathName,

  _Out_opt_  LPTSTR lpVolumeNameBuffer,          /* 이름을 저장하는 버퍼 */

  _In_          DWORD nVolumeNameSize,

  _Out_opt_  LPDWORD lpVolumeSerialNumber,

  _Out_opt_  LPDWORD lpMaximumComponentLength,

  _Out_opt_  LPDWORD lpFileSystemFlags,

  _Out_opt_  LPTSTR lpFileSystemNameBuffer,    

  _In_       DWORD nFileSystemNameSize

);

 

지정된 루트 디렉터리에 관한 시스템 볼륨 정보를 얻는 함수인 GetVolumeInformation 를 이용해서 볼륨 정보를 얻고 있는부분이다.

다양한 정보가 입력되지만 우리가 주목할부분은 드라이브의 이름에 대한 부분이다. 여기서는 VolumeNameBuffer에 드라이브의 이름이 저장된다.

 

0040107D PUSH 0  pFileSystemNameSize = NULL nFileSystemNameSize
0040107F PUSH 0  pFileSystemNameBuffer = NULL lpFileSystemNameBuffer
00401081 PUSH 07.004020C8 pFileSystemFlags = 07.004020C8 lpFileSystemFlags
00401086 PUSH 07.00402190 pMaxFilenameLength = 07.00402190 lpMaximumComponentLength
0040108B PUSH 07.00402194 pVolumeSerialNumber = 07.00402194 lpVolumeSerialNumber
00401090 PUSH 32 MaxVolumeNameSize = 32 (50.) nVolumeNameSize
00401092 PUSH 07.0040225C VolumeNameBuffer = 07.0040225C lpVolumeNameBuffer
00401097 PUSH 0 RootPathName = NULL lpRootPathName
00401099 CALL 00401153 GetVolumeInformationA GetVolumeInformation

 => 우리가 원하는 드라이브의 이름은 0040225C에 저장된다. 이 주소를 이용하면 드라이브 이름을 임의로 변경 할 수 있다.

 

-(0040109E ~ 004010A8) Istrcat

더보기

LPTSTR WINAPI lstrcat(

  _Inout_  LPTSTR lpString1,                /* ConcatString */

  _In_      LPTSTR lpString2                  /* StringToAdd  */

   );

 

lpString1(ConcatString) + lpString2(StringToAdd) 값을 반환하는 함수. 어셈블리 코드를 통해서 보면 아래와 같다.

 

0040109E PUSH 07.004023F3 StringToAdd = "4562-ABEX" IpString2
004010A3 PUSH 07.0040225C (디스크 이름) ConcatString = "" IpString1
004010A8 CALL <JMP.&KERNEL32.IstrcatA> IstrcatA Istrcat

" " + "4562-ABEX" 값인 "4562-ABEX" 를 반환해 0040225C에 저장한다.

 

-(004010AD ~ 004010CD) 연산

더보기

0040225C ~ 0040225F 값들을 어셈블리 명령어로 아래와 같이 연산한다.

004010AD MOV DL,2 DL 의 값을 2로 설정한다.
004010AF ADD DWORD PTR DS:[40225C],1 40225C 값에 1을 더한다.
004010B6 ADD DWORD PTR DS:[40225D],1 40225D 값에 1을 더한다.
004010BD ADD DWORD PTR DS:[40225E],1 40225E 값에 1을 더한다.
004010C4 ADD DWORD PTR DS:[40225F],1 40225F 값에 1을 더한다.
004010CB DEC DL DL 의 값에서 1을 뺀다.
004010CD JNZ SHORT 07.004010AF DL의 값이 0인지검사하고 0이 아니면 004010AF로 점프한다.

=> 0040225C (디스크 이름 저장 주소) 의 4자리 값들에 대해서 2씩 더해주는 연산을하고 있는것이다. 만약에 디스크이름이 Codeengn 이라면 Code 값이 2번 증가한 값 + "engn" 이 될것이다.

 

-(004010CF ~ 004010E8) IstractA

더보기

"L2C - 5781" 과 "6784 - ABEX" 값을 더해서 "LC2 - 57816784 - ABEX" 값을 더해서 00402000에 주소에 반환한다. (위에서 서술한 내용과 같으므로 생략)

 

-(004010ED ~ 004010F7) IstrcmpiA

더보기

사용자가 입력한 시리얼값과 위에서 만들어진 시리얼값(LC2 - 57816784 - ABEX)을 IstrcmpiA 함수를 이용해 비교한다.

 

위의 과정을 거쳐 입력값과 시리얼값이 같다면 인증 성공!

#004010FF 의 점프 분기문을 무조건 성공 MessageBoxA로 점프시키면 어떤 시리얼 값을 넣어도 인증 성공되는 크랙버젼을 만들 수 있다.

'[Riversing] > [코드엔진] BASIC' 카테고리의 다른 글

[코드엔진] basic9  (0) 2020.03.31
[코드엔진] basic8  (0) 2020.03.31
[코드엔진] basic6  (0) 2020.03.25
[코드엔진] basic5  (0) 2020.03.25
[코드엔진] basic4  (0) 2020.03.24