본문 바로가기

S-DEV/패커 제작

Reverse Engineering

728x90

Packer를 배우기 위한 과정

• VM을 공부하기 전에 OPCODE를 잘 다루어야 한다

수행할 연산자를 표시하는 것이 OPCODE (Operation Code) 라고 한다. 이는 "함수 연산", "자료 전달", "제어", "입출력" 으로 세분화 된다.

 

 

- Hello-SDEV를 출력하는 C코드를 작성 후 어셈블리어로 변환하여 살펴보고 똑같이 작성하라

#include <stdio.h>

int main()
{
	printf("Hello S-DEV");
}
#include <stdio.h>

char message[] = "Hello S-DEV";
char format[] = "%s\n";

int main()
{
    __asm
    {
    	// message 주소를 eax에 레지스터에 로드한다.
        lea eax, message
        // 스택에 푸시
        push eax
		
        // 형식 문자열을 스택에 푸시
        lea eax, format
        push eax
		// printf 함수 호출
        call printf
		
        // 스택 정리
        add esp, 8
    }
}

 

- 두 숫자의 합을 계산하는 함수를 작성 후, 어셈블리어로 변환하여 살펴보고 똑같이 작성하라 

#include <stdio.h>

int a = 5;
int b = 10;
char format[] = "result : %d\n";

int main()
{
    __asm
    {
        mov eax, [a]
        mov edx, [b]
        add eax, edx
        push eax

        lea eax, format
        push eax

        call printf

        add esp, 8
    }

}

 

- 컴퓨터와 가위바위보를 진행하는 함수를 작성 후, 어셈블리어로 변환하여 살펴보고 똑같이 작성하라

> 디버그 했을 때

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main() {
0081199F  add         byte ptr [ebx],dh  
008119A1  lds         ecx,fword ptr [ecx+10B9FC45h]  
008119A7  rol         byte ptr [ecx-6661800h],0FFh  
008119AE  jmp         fword ptr [edx]  
    // 시드 값 설정을 위해 시간을 사용
    srand(time(NULL));
008119B1  call        time (0811D00h)  
008119B6  add         esp,4  
008119B9  mov         esi,esp  
008119BB  push        eax  
008119BC  call        dword ptr [__imp__srand (081B178h)]  
008119C2  add         esp,4  
008119C5  cmp         esi,esp  
008119C7  call        __RTC_CheckEsp (0811267h)  

    printf("가위(1), 바위(2), 보(3) 중 하나를 선택하세요: ");
008119CC  push        offset string "\xb0\xa1\xc0\xa7(1), \xb9\xd9\xc0\xa7(2), \xba\xb8(3) \xc1\xdf \xc7\xcf\xb3\xaa@"... (0817B30h)  
008119D1  call        _printf (08110DCh)  
008119D6  add         esp,4  
    int userChoice;
    scanf("%d", &userChoice);
008119D9  lea         eax,[userChoice]  
008119DC  push        eax  
008119DD  push        offset string "%d" (0817B68h)  
008119E2  call        _scanf (0811037h)  
008119E7  add         esp,8  

    if (userChoice < 1 || userChoice > 3) {
008119EA  cmp         dword ptr [userChoice],1  
008119EE  jl          __$EncStackInitStart+6Ah (08119F6h)  
008119F0  cmp         dword ptr [userChoice],3  
008119F4  jle         __$EncStackInitStart+81h (0811A0Dh)  
        printf("잘못된 입력입니다. 가위(1), 바위(2), 보(3) 중에서 선택하세요.\n");
008119F6  push        offset string "\xc0\xdf\xb8\xf8\xb5\xc8 \xc0\xd4\xb7\xc2\xc0\xd4\xb4\xcf\xb4\xd9. \xb0\xa1\xc0\xa7(1), \xb9\xd9\xc0@"... (0817B6Ch)  
008119FB  call        _printf (08110DCh)  
00811A00  add         esp,4  
        return 1; // 프로그램 종료
00811A03  mov         eax,1  
00811A08  jmp         __$EncStackInitStart+17Fh (0811B0Bh)  
    }

    // 1: 가위, 2: 바위, 3: 보
    int computerChoice = rand() % 3 + 1;  div idiv  -> add + 1
00811A0D  mov         esi,esp  
00811A0F  call        dword ptr [__imp__rand (081B174h)]  
00811A15  cmp         esi,esp  
00811A17  call        __RTC_CheckEsp (0811267h)  내부적으로 esp가 정리가 되었는지 확인   
00811A1C  cdq  
00811A1D  mov         ecx,3  
00811A22  idiv        eax,ecx  
00811A24  add         edx,1  
00811A27  mov         dword ptr [computerChoice],edx  

    printf("컴퓨터의 선택: ");
00811A2A  push        offset string "\xc4\xc4\xc7\xbb\xc5\xcd\xc0\xc7 \xbc\xb1\xc5\xc3: " (0817BB8h)  
00811A2F  call        _printf (08110DCh)  
00811A34  add         esp,4  
    if (computerChoice == 1) {
00811A37  cmp         dword ptr [computerChoice],1  
00811A3B  jne         __$EncStackInitStart+0C0h (0811A4Ch)  
        printf("가위\n");
00811A3D  push        offset string "\xb0\xa1\xc0\xa7\n" (0817BCCh)  
00811A42  call        _printf (08110DCh)  
00811A47  add         esp,4  
    }
00811A4A  jmp         __$EncStackInitStart+0E2h (0811A6Eh)  
    else if (computerChoice == 2) {
00811A4C  cmp         dword ptr [computerChoice],2  
00811A50  jne         __$EncStackInitStart+0D5h (0811A61h)  
        printf("바위\n");
00811A52  push        offset string "\xb9\xd9\xc0\xa7\n" (0817BD4h)  
00811A57  call        _printf (08110DCh)  
00811A5C  add         esp,4  
    }
00811A5F  jmp         __$EncStackInitStart+0E2h (0811A6Eh)  
    else {
        printf("보\n");
00811A61  push        offset string "\xba\xb8\n" (0817BDCh)  
00811A66  call        _printf (08110DCh)  
00811A6B  add         esp,4  
    }

    printf("당신의 선택: ");
00811A6E  push        offset string "\xb4\xe7\xbd\xc5\xc0\xc7 \xbc\xb1\xc5\xc3: " (0817BE0h)  
00811A73  call        _printf (08110DCh)  
00811A78  add         esp,4  
    if (userChoice == 1) {
00811A7B  cmp         dword ptr [userChoice],1  
00811A7F  jne         __$EncStackInitStart+104h (0811A90h)  
        printf("가위\n");
00811A81  push        offset string "\xb0\xa1\xc0\xa7\n" (0817BCCh)  
00811A86  call        _printf (08110DCh)  
00811A8B  add         esp,4  
    }
00811A8E  jmp         __$EncStackInitStart+126h (0811AB2h)  
    else if (userChoice == 2) {
00811A90  cmp         dword ptr [userChoice],2  
00811A94  jne         __$EncStackInitStart+119h (0811AA5h)  
        printf("바위\n");
00811A96  push        offset string "\xb9\xd9\xc0\xa7\n" (0817BD4h)  
00811A9B  call        _printf (08110DCh)  
00811AA0  add         esp,4  
    }
00811AA3  jmp         __$EncStackInitStart+126h (0811AB2h)  
    else {
        printf("보\n");
00811AA5  push        offset string "\xba\xb8\n" (0817BDCh)  
00811AAA  call        _printf (08110DCh)  
00811AAF  add         esp,4  
    }

    // 결과 결정
    if (userChoice == computerChoice) {
00811AB2  mov         eax,dword ptr [userChoice]  
00811AB5  cmp         eax,dword ptr [computerChoice]  
00811AB8  jne         __$EncStackInitStart+13Dh (0811AC9h)  
        printf("비겼습니다!\n");
00811ABA  push        offset string "\xba\xf1\xb0\xe5\xbd\xc0\xb4\xcf\xb4\xd9!\n" (0817BF0h)  
00811ABF  call        _printf (08110DCh)  
00811AC4  add         esp,4  
    }
00811AC7  jmp         __$EncStackInitStart+17Dh (0811B09h)  
    else if ((userChoice == 1 && computerChoice == 3) ||
        (userChoice == 2 && computerChoice == 1) ||
00811AC9  cmp         dword ptr [userChoice],1  
00811ACD  jne         __$EncStackInitStart+149h (0811AD5h)  
00811ACF  cmp         dword ptr [computerChoice],3  
00811AD3  je          __$EncStackInitStart+161h (0811AEDh)  
00811AD5  cmp         dword ptr [userChoice],2  
00811AD9  jne         __$EncStackInitStart+155h (0811AE1h)  
00811ADB  cmp         dword ptr [computerChoice],1  
00811ADF  je          __$EncStackInitStart+161h (0811AEDh)  
00811AE1  cmp         dword ptr [userChoice],3  
00811AE5  jne         __$EncStackInitStart+170h (0811AFCh)  
00811AE7  cmp         dword ptr [computerChoice],2  
00811AEB  jne         __$EncStackInitStart+170h (0811AFCh)  
        (userChoice == 3 && computerChoice == 2)) {
        printf("당신이 이겼습니다!\n");
00811AED  push        offset string "\xb4\xe7\xbd\xc5\xc0\xcc \xc0\xcc\xb0\xe5\xbd\xc0\xb4\xcf\xb4\xd9!\n" (0817C00h)  
00811AF2  call        _printf (08110DCh)  
00811AF7  add         esp,4  
    }
00811AFA  jmp         __$EncStackInitStart+17Dh (0811B09h)  
    else {
        printf("컴퓨터가 이겼습니다!\n");
00811AFC  push        offset string "\xc4\xc4\xc7\xbb\xc5\xcd\xb0\xa1 \xc0\xcc\xb0\xe5\xbd\xc0\xb4\xcf\xb4\xd9!\n" (0817C18h)  
00811B01  call        _printf (08110DCh)  
00811B06  add         esp,4  
    }

 

 

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

char message[] = "가위(1), 바위(2), 보(3) 중 하나 선택";
char format[] = "%s\n";

int userChoice;
char format1[] = "%d";

int computer = 0;
// 
char dr[] = "비겼습니다.";
char wi[] = "이겼습니다.";
char lo[] = "졌습니다.";
char formatd[] = "%d\n";

int main()
{

	srand(time(NULL));
	/*	printf("%p\n", temp);
	__asm {
		lea eax, temp
		push eax
		call printf
		add esp,4
		
	}*/

	__asm 
	{
		// 가위 바위 보 선택 
		lea eax,  message
		push eax
		lea eax, format
		push eax
		call printf
		add esp, 8

		// 사용자 입력 값
		lea eax,[userChoice]
		push eax
		lea eax, format1
		push eax
		call scanf
		add esp, 8

		// 컴퓨터 값
		// rand()%3+1
		mov esi, esp
		call rand  // - > return eax		
		//mov edx, 0x1  // edx require 0 -> cdq  다른 방법으로는 xor edx, edx 로 사용할 수 있음
		cdq
		mov ecx, 0x3
		// idiv를 하면 eax에는 몫에 저장, edx에는 나머지 값이 저장
		idiv ecx
		add edx, 1
		mov dword ptr[computer], edx
		push edx
		push offset formatd
		call dword ptr printf
		add esp, 8

		 
		// 결과 값 출력
		mov eax, dword ptr[userChoice]
		cmp eax, dword ptr[computer]
		// 값이 같을 경우
		je Draw

		// 첫 번째 조건 (userChoice == 1 && computer == 3)
		cmp dword ptr[userChoice], 1
		jne First
		cmp dword ptr[computer], 3
		jne First
		je Win

		// 두 번째 조건 (userChoice == 2 && computer == 1)
		First:
			cmp dword ptr[userChoice], 2
			jne Second

			cmp dword ptr[computer], 1
			jne Lose
			je Win

		// 세 번째 조건 (userChoice == 3 && computer == 2
		Second:
			cmp dword ptr[userChoice], 3
			jne Lose

			cmp dword ptr[computer], 2
			jne Lose
			je Win


		Draw: 
			push offset dr
			call printf
			add esp, 4
			jmp end

		Win:
			//mov eax, wi
			push offset wi
			call printf
			add esp, 4
			jmp end

		Lose:
			//mov eax, lo
			push offset lo
			call printf
			add esp, 4
			jmp end

		end:


	}
}

'S-DEV > 패커 제작' 카테고리의 다른 글

Tiny Encryption Algorithm  (0) 2023.08.31
codeengn  (0) 2023.08.24