reversing/리버싱 코드 복원

03.Control_Statements_Quiz_07

grinidia 2025. 4. 22. 20:10

 


문제

어셈블리코드 - 1
어셈블리코드 - 2
실행화면

 


문제 풀이

07_Quiz.exe 를 OllyDBG에서 확인하면 아래와 같다.

00401000                            /$  55              PUSH    EBP
00401001                            |.  8BEC            MOV     EBP, ESP
00401003                            |.  83EC 10         SUB     ESP, 10
00401006                            |.  6A 00           PUSH    0                                               ; /Style = MB_OK|MB_APPLMODAL
00401008                            |.  68 30504000     PUSH    03_07_Qu.00405030                               ; |Title = "ITBANK"
0040100D                            |.  68 38504000     PUSH    03_07_Qu.00405038                               ; |Text = "Insert Argument"
00401012                            |.  6A 00           PUSH    0                                               ; |hOwner = NULL
00401014                            |.  FF15 94404000   CALL    DWORD PTR DS:[<&USER32.MessageBoxA>]            ; \MessageBoxA

0040101A                            |.  C745 F4 0000000>MOV     DWORD PTR SS:[EBP-C], 0
// EBP-C 에 0을 할당

// for 문 진입
00401021                            |.  EB 09           JMP     SHORT 03_07_Qu.0040102C
00401023                            |>  8B45 F4         /MOV     EAX, DWORD PTR SS:[EBP-C]                      ;  kernel32.7C8399F3
00401026                            |.  83C0 01         |ADD     EAX, 1
00401029                            |.  8945 F4         |MOV     DWORD PTR SS:[EBP-C], EAX
0040102C                            |>  8B4D 10          MOV     ECX, DWORD PTR SS:[EBP+10]
0040102F                            |.  034D F4         |ADD     ECX, DWORD PTR SS:[EBP-C]                      ;  kernel32.7C8399F3
00401032                            |.  0FBE11          |MOVSX   EDX, BYTE PTR DS:[ECX]
00401035                            |.  85D2            |TEST    EDX, EDX                                       ;  ntdll.KiFastSystemCallRet
00401037                            |.  74 02           |JE      SHORT 03_07_Qu.0040103B
00401039                            |.^ EB E8           \JMP     SHORT 03_07_Qu.00401023

// _n1+1을 함수에 매개변수로 사용하는 로직
0040103B                            |>  8B45 F4         MOV     EAX, DWORD PTR SS:[EBP-C]                       ;  kernel32.7C8399F3
0040103E                            |.  83C0 01         ADD     EAX, 1
00401041                            |.  50              PUSH    EAX
00401042                            |.  E8 9D010000     CALL    03_07_Qu.004011E4

00401047                            |.  83C4 04         ADD     ESP, 4
// PUSH 한 EAX, 1 없앤다.

0040104A                            |.  8945 F0         MOV     DWORD PTR SS:[EBP-10], EAX
// malloc 함수 결과 값 [EBP-10] 저장 (반환 값이 PTR이므로 포인터 주소 값을 반환으로 유추가능)

0040104D                            |.  8B4D F0         MOV     ECX, DWORD PTR SS:[EBP-10]
00401050                            |.  894D FC         MOV     DWORD PTR SS:[EBP-4], ECX
// [EBP-10]를 [EBP-4] 포인터 변수에 다시 할당한다. 

00401053                            |.  C745 F4 0000000>MOV     DWORD PTR SS:[EBP-C], 0
// 기존의 [EBP-4]에 0을 할당한다.

// While 문 진입
0040105A                            |>  8B55 10         /MOV     EDX, DWORD PTR SS:[EBP+10]
0040105D                            |.  0355 F4         |ADD     EDX, DWORD PTR SS:[EBP-C]                      ;  kernel32.7C8399F3
00401060                            |.  0FBE02          |MOVSX   EAX, BYTE PTR DS:[EDX]
00401063                            |.  85C0            |TEST    EAX, EAX
00401065                            |.  0F84 BB000000   |JE      03_07_Qu.00401126
// 0인지 확인하는 로직 

// 첫 번째 분기 (if)
0040106B                            |.  8B4D 10         |MOV     ECX, DWORD PTR SS:[EBP+10]
0040106E                            |.  034D F4         |ADD     ECX, DWORD PTR SS:[EBP-C]                      ;  kernel32.7C8399F3
00401071                            |.  0FBE11          |MOVSX   EDX, BYTE PTR DS:[ECX]
00401074                            |.  83FA 41         |CMP     EDX, 41
00401077                            |.  7C 14           |JL      SHORT 03_07_Qu.0040108D
00401079                            |.  8B45 10         |MOV     EAX, DWORD PTR SS:[EBP+10]
0040107C                            |.  0345 F4         |ADD     EAX, DWORD PTR SS:[EBP-C]                      ;  kernel32.7C8399F3
0040107F                            |.  0FBE08          |MOVSX   ECX, BYTE PTR DS:[EAX]
00401082                            |.  83F9 5A         |CMP     ECX, 5A
00401085                            |.  7F 06           |JG      SHORT 03_07_Qu.0040108D
00401087                            |.  C645 F8 41      |MOV     BYTE PTR SS:[EBP-8], 41
0040108B                            |.  EB 63           |JMP     SHORT 03_07_Qu.004010F0

// 두 번째 분기 (else if)
0040108D                            |>  8B55 10         |MOV     EDX, DWORD PTR SS:[EBP+10]
00401090                            |.  0355 F4         |ADD     EDX, DWORD PTR SS:[EBP-C]                      ;  kernel32.7C8399F3
00401093                            |.  0FBE02          |MOVSX   EAX, BYTE PTR DS:[EDX]
00401096                            |.  83F8 61         |CMP     EAX, 61
00401099                            |.  7C 14           |JL      SHORT 03_07_Qu.004010AF
0040109B                            |.  8B4D 10         |MOV     ECX, DWORD PTR SS:[EBP+10]
0040109E                            |.  034D F4         |ADD     ECX, DWORD PTR SS:[EBP-C]                      ;  kernel32.7C8399F3
004010A1                            |.  0FBE11          |MOVSX   EDX, BYTE PTR DS:[ECX]
004010A4                            |.  83FA 7A         |CMP     EDX, 7A
004010A7                            |.  7F 06           |JG      SHORT 03_07_Qu.004010AF
004010A9                            |.  C645 F8 61      |MOV     BYTE PTR SS:[EBP-8], 61
004010AD                            |.  EB 41           |JMP     SHORT 03_07_Qu.004010F0

// 세 번째 분기 (else if)
004010AF                            |>  8B45 10         |MOV     EAX, DWORD PTR SS:[EBP+10]
004010B2                            |.  0345 F4         |ADD     EAX, DWORD PTR SS:[EBP-C]                      ;  kernel32.7C8399F3
004010B5                            |.  0FBE08          |MOVSX   ECX, BYTE PTR DS:[EAX]
004010B8                            |.  83F9 20         |CMP     ECX, 20
004010BB                            |.  75 1B           |JNZ     SHORT 03_07_Qu.004010D8
004010BD                            |.  8B55 FC         |MOV     EDX, DWORD PTR SS:[EBP-4]
004010C0                            |.  0355 F4         |ADD     EDX, DWORD PTR SS:[EBP-C]                      ;  kernel32.7C8399F3
004010C3                            |.  8B45 10         |MOV     EAX, DWORD PTR SS:[EBP+10]
004010C6                            |.  0345 F4         |ADD     EAX, DWORD PTR SS:[EBP-C]                      ;  kernel32.7C8399F3
004010C9                            |.  8A08            |MOV     CL, BYTE PTR DS:[EAX]
004010CB                            |.  880A            |MOV     BYTE PTR DS:[EDX], CL
004010CD                            |.  8B55 F4         |MOV     EDX, DWORD PTR SS:[EBP-C]                      ;  kernel32.7C8399F3
004010D0                            |.  83C2 01         |ADD     EDX, 1
004010D3                            |.  8955 F4         |MOV     DWORD PTR SS:[EBP-C], EDX                      ;  ntdll.KiFastSystemCallRet
004010D6                            |.^ EB 82           |JMP     SHORT 03_07_Qu.0040105A
// 조건분기를 완료했는데 반복문의 처음으로 돌아간다.
// 이를 보고 continue; 를 유추할 수 있다.

004010D8                            |>  6A 00           |PUSH    0                                              ; /Style = MB_OK|MB_APPLMODAL
004010DA                            |.  68 48504000     |PUSH    03_07_Qu.00405048                              ; |Title = "ITBANK"
004010DF                            |.  68 50504000     |PUSH    03_07_Qu.00405050                              ; |Text = "Insert An Alphabet"
004010E4                            |.  6A 00           |PUSH    0                                              ; |hOwner = NULL
004010E6                            |.  FF15 94404000   |CALL    DWORD PTR DS:[<&USER32.MessageBoxA>]           ; \MessageBoxA
004010EC                            |.  33C0            |XOR     EAX, EAX
004010EE                            |.  EB 69           |JMP     SHORT 03_07_Qu.00401159
// while 문 종료

004010F0                            |>  8B45 10         |MOV     EAX, DWORD PTR SS:[EBP+10]
004010F3                            |.  0345 F4         |ADD     EAX, DWORD PTR SS:[EBP-C]                      ;  kernel32.7C8399F3
004010F6                            |.  0FBE00          |MOVSX   EAX, BYTE PTR DS:[EAX]
004010F9                            |.  0FBE4D F8       |MOVSX   ECX, BYTE PTR SS:[EBP-8]
004010FD                            |.  2BC1            |SUB     EAX, ECX
004010FF                            |.  83C0 03         |ADD     EAX, 3
00401102                            |.  99              |CDQ
// 부호있을 나눗셈을 준비한다.

00401103                            |.  B9 1A000000     |MOV     ECX, 1A
00401108                            |.  F7F9            |IDIV    ECX
// EAX에 ECX를 나눈다.

0040110A                            |.  0FBE45 F8       |MOVSX   EAX, BYTE PTR SS:[EBP-8]
0040110E                            |.  03D0            |ADD     EDX, EAX
// n4를 더한다

00401110                            |.  8B4D FC         |MOV     ECX, DWORD PTR SS:[EBP-4]
00401113                            |.  034D F4         |ADD     ECX, DWORD PTR SS:[EBP-C]                      ;  kernel32.7C8399F3
00401116                            |.  8811            |MOV     BYTE PTR DS:[ECX], DL
00401118                            |.  8B55 F4         |MOV     EDX, DWORD PTR SS:[EBP-C]                      ;  kernel32.7C8399F3
0040111B                            |.  83C2 01         |ADD     EDX, 1
0040111E                            |.  8955 F4         |MOV     DWORD PTR SS:[EBP-C], EDX                      ;  ntdll.KiFastSystemCallRet
00401121                            |.^ E9 34FFFFFF     \JMP     03_07_Qu.0040105A
// while 문 종료 

00401126                            |>  8B45 FC         MOV     EAX, DWORD PTR SS:[EBP-4]
00401129                            |.  0345 F4         ADD     EAX, DWORD PTR SS:[EBP-C]                       ;  kernel32.7C8399F3
0040112C                            |.  C600 00         MOV     BYTE PTR DS:[EAX], 0
0040112F                            |.  68 64504000     PUSH    03_07_Qu.00405064                               ;  ASCII "LWedqn"
00401134                            |.  8B4D FC         MOV     ECX, DWORD PTR SS:[EBP-4]
00401137                            |.  51              PUSH    ECX
00401138                            |.  E8 23000000     CALL    03_07_Qu.00401160
// strcmp 함수 호출

0040113D                            |.  83C4 08         ADD     ESP, 8
// [EBP-4] [EBP-C] 둘다 없앤다

00401140                            |.  85C0            TEST    EAX, EAX
00401142                            |.  75 13           JNZ     SHORT 03_07_Qu.00401157
// strcmp가 0인지 확인한다.

00401144                            |.  6A 00           PUSH    0                                               ; /Style = MB_OK|MB_APPLMODAL
00401146                            |.  68 6C504000     PUSH    03_07_Qu.0040506C                               ; |Title = "ITBANK"
0040114B                            |.  8B55 10         MOV     EDX, DWORD PTR SS:[EBP+10]                      ; |
0040114E                            |.  52              PUSH    EDX                                             ; |Text = "횒\xA4$"
0040114F                            |.  6A 00           PUSH    0                                               ; |hOwner = NULL
00401151                            |.  FF15 94404000   CALL    DWORD PTR DS:[<&USER32.MessageBoxA>]            ; \MessageBoxA
00401157                            |>  33C0            XOR     EAX, EAX
00401159                            |>  8BE5            MOV     ESP, EBP
0040115B                            |.  5D              POP     EBP                                             ;  kernel32.7C816D4F
0040115C                            \.  C2 1000         RETN    10

 

C 코드로 작성하면 아래와 같다.

#include <windows.h>
#include <stdlib.h>

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
   MessageBox(NULL, "Insert Argument", "ITBANK", MB_OK);

   int _n1;
   for(_n1=0; lpCmdLine[_n1] !=0; _n1++);
   char *_n2 = (char *)malloc(_n1+1);
   char *n3 = _n2;
   char n4;
   _n1 = 0;

   while(lpCmdLine[_n1])
   {
      if (lpCmdLine[_n1] >= 'A' && lpCmdLine[_n1] <= 'Z') 
      {
         n4 = 'A';
      }
      else if (lpCmdLine[_n1] >= 'a' && lpCmdLine[_n1] <= 'z')
      {
         n4 = 'a';
      }
      else if(lpCmdLine[_n1] == ' ')
      {
         n3[_n1] = lpCmdLine[_n1];
         _n1++;
          continue;
      }
      else
      {
         MessageBox(NULL, "Insert An Alphabet", "ITBANK", MB_OK);
         return 0;
      }
      

      n3[_n1] = (lpCmdLine[_n1] - n4 + 3) % 26 + n4;
      _n1 = _n1 + 1;

   }

   n3[_n1] = 0x00;
   if(strcmp(n3, "LWedqn") == 0)
   {
      MessageBox(NULL, lpCmdLine, "ITBANK", MB_OK);
   }

   return 0;
}