2007. 8. 17. 10:08
DevX -> Seed 챕터는 Win32 API를 어셈블리를 이용해서 제작하는 DevX의 메인강좌를 진행하기
위해서 기반이 되는 여러가지 정보를 특정순서 없이 기술하는 용도의 서브챕터입니다.

윈도우 프로그래밍에 어셈블리를 사용하는 것은 너무나도 쉽다! 라고는 말씀드릴 수 없겠습니다만,
약간의 기본만 익혀두신다면 여타 다른 고급언어보다 깔끔한 스타일과 보다 진보적인(??) 프로그래밍을
하실 수 있습니다.  개발 속도를 요한다면 빌려다 쓰고, 자신만의 시스템으로 개조할려면 직접 만들고,
어셈블리로 못하는것은 없다!! 라는 진리는 변함이 없습니다.  못하는것이 없다는 전제조건에 바로
여기에 있는 "Seed" 챕터가 도움을 드리기 위해서 존재합니다. 

분명 크게 넘어야할 산이 많습니다만, 한걸음씩 정진하시기 바라며, 마지막으로 파이팅을......


# 작업의 정석

본 가이드는 Masm32 Version 9 시스템을 각자가 설치한 후에 아무런 추가작업을 하지 않았다는
가정하에서, 화면에 메세지박스를 띄우는 프로그램을 작성해 본 후, 코드를 이해하고, 실행파일을
만들어서, 실행파일을 역어셈블러로 읽어들여서 어셈블리 소스코드와 실행파일의 차이점에
대해서 알아보고져 설명하는 가이드 입니다. 이러한 것을 리버스엔지니어링 이라고 하며, 유일하게
어셈블리로만 작업합니다. (간혹 C나 기타언어를 자신만의 라이브러리로 개조해서 하기도합니다.)
대부분 리버스엔지니어링은 프로그램의 패치나 크랙 해킹등에 사용합니다만, 한분야일뿐입니다.
또한가지, 가이드를 숙지하신 후 느끼실점이겠지만, 어셈블리 소스와 실행파일의 역어셈블의
구조가 별차이가 없다는 것을 알게 되실겁니다.

이말은 C나 델파이 비주얼베이직등으로 만든 고급언어들은 소스코드를 제공하지 않으므로해서
저작권과 내용을 보호합니다. 단지 실행파일만 제공해주게 되니까요. 하지만 역어셈블은 실행파일을
어셈블리언어로 만들어주기 때문에, 늘 어셈블리에 익숙해져계시다면, 별다른 소스코드는 필요
없습니다. 그래서 크랙이나 여러가지 행위가 가능한 것입니다. VC++의 비밀번호 체크루틴은
어셈블리에서 어떠한 형식으로 나타나는지만 알게되면????  번호검사루틴을 항상 참으로 점프
시켜버릴 수도 있겠지요.. 혹은 정품등록 후의 환영메세지가 어디에서 호출되었는지를 찾아내서
무조건 그부분으로 점프하게끔 할 수도 있으며, 조건검사루틴을 NOP(90H : No Operation)로 대체
해서 검사자체를 없애버릴 수 도 있겠네요.........  

더이상 잔소리성 설명은 하지 않아도 여러분들은 무슨뜻인지를 이해하셨을거라 생각하면서,
Masm32를 이용해서 MessageBox.exe파일을 생성하고, 실행해 보고, 역어셈블해서 실제 소스와
어떻게 다른지를 살펴보도록 하겠습니다.  가이드를 진행하기 위해서는 Masm32V9.exe파일을
시스템에 설치하셔야 합니다.   설치법을 모르신다면 아래의 링크를 클릭하셔서 프로그램과
설치방법을 익혀두시기 바랍니다.....  필수입니다.!!

http://www.openserver.co.kr/01_DevX_Environment.mht 
     Masm32V9설치 및 WinASM IDE설치가이드




# 작업 01. MessageBox.ASM 작성

가장 먼저, 화면에 메세지를 표시하는 간단한 프로그램을 작성해야겠지요?
WinASM IDE를 사용해서 작성하셔도 됩니다. 하지만 본 가이드에서는 Masm32V9를 설치하면
기본으로 설치되는 Qeditor 를 이용해 보도록 하겠습니다. 어떠한 툴을 이용해도 상관 없습니다.
Notapad(메모장)로 만들어서 커맨드창을 열어서 수동으로 어셈블해도 상관없습니다.
본 가이드는 체험용도 이므로 Qeditor를 사용하도록 하겠습니다.

Masm32설치폴더에서 Qeditor.exe를 실행합니다. 혹은 바탕화면에 바로가기가 있다면 실행합니다.

사용자 삽입 이미지

상기 화면과 같이 덩그러니 나타납니다. 무엇을 해야할지 막막하신가요?? ㅎㅎ
지금 자신이 무엇을 하고 있는지를 정확히 알고 계셔야 합니다. 어셈블리 소스파일을 입력해서
ml.exe로 어셈블과 링킹을 해서 messagebox.exe 라는 실행파일을 만들기 위해서 Qeditor를
실행했습니다. Qeditor 로만 모든 작업을 완성할 수 있습니다. 

이제는 아래의 소스를 입력하시던지, 혹은 복사/붙여넣기를 하시길 바랍니다.
;---------------------------------------------------------------------
.386
.model flat,stdcall
option Casemap:none

include  \masm32\include\windows.inc
include  \masm32\include\user32.inc
include  \masm32\include\kernel32.inc


includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib

.data

MsgTitle    db  "MessageBox Testing", 00H
MsgText     db  "안녕하세요? 이것은 메세지박스입니다", 0DH, 0AH
            db  "만든사람은 권필진 입니다", 00H


.code
Start:
    invoke MessageBox, 00H, Addr MsgText, Addr MsgTitle, MB_OK
    invoke ExitProcess, 00H

end Start
;---------------------------------------------------------------------

사용자 삽입 이미지

현재상태에서 저장을 해야합니다. Qeditor는 여러가지 불편한 점이 있습니다. API함수의 자동완성기능
과 파일 자동저장 후 어셈블링 기능등 여러가지 불편한 점이 많습니다. 하지만 메모장 보다는 강력
합니다. 나중에는 WinASM IDE를 사용합니다. 얼마나 편리한지를 느끼시겠지요....
Qeditor에서 내용을 입력했다고 하더라도, 어셈블하게 되면 ML.EXE는 실제 디스크에 저장된 파일을
기준으로 해서 어셈블링 작업을 하게 됩니다. 그래서 반드시 저장해야 합니다. 내용이 수정되어도
반드시 저장하시기 바랍니다....   "Ctrl + S"키를 누르시거나 "File -> Save"를 선택하시거나 디스켓모양
의 아이콘을 눌러서 저장하시기 바랍니다. 본 가이드에서는 "C:\Temp\MessageBox"폴더에
MessageBox.asm 이라는 파일명으로 저장하겠습니다.

사용자 삽입 이미지

저장하셨다면 이제는 어셈블 -> 링크 과정을 수행해야겠지요... Qeditor에서는 Project메뉴의 Build All
명령만 내려주면 자동으로 처리합니다. (커맨드창을 생성한 후 하나씩 수행합니다)
본 가이드에서는 에러가 발생할 확률은 0%입니다. 에러가 발생하였다면, 자신의 손가락을 조사하시기
바랍니다......  혹은 Qeditor의 편집화면에서 우측버튼을 눌러서 Project -> Build All 을 선택해도
마찬가지 입니다.

사용자 삽입 이미지


사용자 삽입 이미지
상기 화면과 같이 표시되면 정상적으로 어셈블링 되었습니다. 2개의 추가적인 파일이 생성되었습니다.
MessageBox.obj 파일과 우리가 원하는 MessageBox.exe파일이 생성되었습니다.
MessageBox.OBJ 파일은 오브젝트 파일이라고 부르며, ASM파일을 어셈블해서 여러가지 메모리정보와
사용한 변수 테이블과 기타 어셈블러가 추가한 내용이 들어있는 기계어파일입니다.
C언어로 컴파일해서도 obj파일이 생성되지요??   맞습니다. 이것이 분할 컴파일이라는 기술입니다.
그래서 C로 개발하든지 델파이의 파스칼로 개발하든지 OBJ파일만 있다면 서로 합쳐버릴 수 있습니다.
하지만, OBJ파일은 실행정보가 빠져있습니다. 메뉴 / 아이콘 / 버전정보 / 그림정보 등의 리소스를
OBJ에 합쳐서 실행가능하도록 만드는 작업을 Link 작업이라고 부릅니다.
ML.EXE는 바로 Masm + Link 의 총체적인 프로그램입니다. C컴파일러도 컴파일만 할 수있게할수
있습니다. 모든언어의 개념은 동일합니다. 사용법만 틀릴뿐입니다.....

너무나 간단하게 MessageBox.exe파일을 생성했습니다. 다른 프로그램도 제작방식은 동일합니다.
단지 들어가는 소스코드의 양이 많을 뿐입니다. 이것을 배워가는 것이 DevX입니다.....^^

"계속 하려면 아무 키나 누르십시요..." 라고 했으니, 아무키나 눌러서 커맨드창을 닫고, Qeditor도
이제는 필요없습니다. 종료하시기 바랍니다.



# 작업 02. MessageBox.exe 실행

상기 작업으로 애써 만든 프로그램이 어떠한 일을 하는 지 살펴보도록 하겠습니다. 먼저 탐색기를
사용하여 c:\Temp\MessageBox\MessageBox.exe 파일을 실행합니다.

사용자 삽입 이미지
무지막지하게 썰렁합니다.... 하지만 이것도 엄연한 윈도우 프로그램입니다. 타이틀바를
가지고 있으며(WS_CAPTION) 타이틀 텍스트도 있고 "확인"버튼도 존재합니다.
윈도우는 모든것이 바로 윈도우 입니다. 그래서 WindowS 입니다.
상기의 메세지 박스는 윈도우프로그래밍할때 줄기차게 사용하는 함수이기도 합니다.
사용자가 설정해주는 부분은 타이틀과 실제 내용과 각종버튼 이며, 나머지 전체틀과 닫기버튼
등은 윈도우가 처리해주는 것입니다. 

위에서 작업했던 어셈블리 소스파일을 유심히 1분만 살펴보시면 대략 알 수 있으신 분들도
계실겁니다. MsgTitle / MsgText 부분에서 내용을 입력하고 MessageBox함수를 호출했다는
것을 말입니다...... 


# 작업 03. W32Dasm 역어셈블러

이제 가장 중요한 작업을 해야겠습니다. MessageBox.EXE파일만 존재한다고 가정하고,
도대체 어찌프로그램을 짯을까? 하고 궁금해하고, 저기 들어있는 내용중에 "권필진" 이라는
이름이 유난히 거슬린다.... 자기이름으로 바꾸어도 보고싶어지기도 하네요.....(전 아닙니다. ^^)
그런데 C로 짯는지 델파이로 짯는지 여하튼 멀로짯는지 몰라도 소스코드가 있다면 변수에서
변경한 후 다시 컴파일 하면 되는데 소스코드는 없고 단지 실행파일만 있습니다.
이것을 가능하게 하는것이 바로 역어셈블러(DisAssembler)입니다.

실행파일은 정해진 규칙(PE파일형식)으로 생성되기 때문에 오버헤드부분(중복)을 제외하면
실제 명령어와 그 명령이 소모하는 인자들을 가려낼 수 있고, 명령어를 역으로 어셈블리 기호
(이것은 니모닉이라 불렀죠? )로 변경할 수 있습니다. 이것이 바로 역어셈블링 기능입니다.
크게 어려운 기술은 아닙니다. 니모닉 연산표만 있으면 실제기계어를 보고 손으로도 역어셈블
할 수 있습니다. (이것을 핸드어셈블 이라 합니다).. 컴퓨터가 사람보다 나은점은 빠르다는것
뿐입니다. 각설하고, 혹시 디버거와 혼동하시지 마시길 바랍니다... 디버거도 역어셈블기능을
가지고 있습니다. 역어셈블러도 디버깅 기능을 가지고 있습니다. 구분은 잘 안하지만 엄연히
두가지는 다른 기능입니다. 같은제품에 포함될 뿐이지요.....
소프트아이스 / IDA / OllyDBG / WinDBG등은 모두 디버거입니다. 실행파일을 한명령어씩
수행하면서 CPU내부의 정보를 살펴가는 도구입니다.

Sourcer / W32Dasm 등은 역어셈블러 입니다. exe파일을 어떠한 구조로 되어있는지를 분석
해주고, 어셈블리 소스파일을 만들어줍니다. (사용한 변수는 실제 기계어에서는 주소로만
나오기 때문에 이해하기 힘듭니다. 역어셈블러가 다시 변수명을 맞춰주기도 합니다.)

W32Dasm 은 아주 유명한 역어셈블러입니다. 네이버나 구글에서 검색해보시기 바랍니다.
크랙툴에서는 필수 유틸리티이기도 합니다.  명령어의 이름이 상당히 난해해보여서 어려워
보입니다만, 어셈블리 하셨던 분이라면 다들 한번씩 들어본 용어들로 되어있습니다.
각설하고, 체험용이므로 무조건 진행해보도록 하겠습니다.

먼저 프로그램이 있어야겠네요...

http://www.openserver.co.kr/w32dasm.exe   를 클릭하셔서 다운로드 받으신 후
실행하셔서 원하는 위치에 설치하시기 바랍니다.
설치하신 후 설치 폴더로 이동하셔서 W32DSM89.EXE  를 실행합니다.

사용자 삽입 이미지
W32Dasm 8.9버전에 여러가지 패치를 가한 버전입니다. 가장사용하기 편하다 해야할까요....
보통 다른 강좌에서 나오는 메뉴와 차이가 납니다. 위치만 다르게 되어있습니다.
화면깨지거나, 폰트가 깨지거나 휠이 작동안하거나 하는데 뭐 사용하기 편하게 패치되어있습니다.
W32Dasm의 메뉴중 "File -> Open File to Disassemble..." 메뉴를 선택해서 원하는 실행파일이나
dll파일을 선택해줍니다. 본 가이드에서는 원하는 파일이 정해져있지요?
c:\Temp\MessageBox\MessageBox.exe 파일을 선택해 줍니다.  프로그램이 작아서 금방
역어셈블 할 것입니다만, 보통의 프로그램은 변환하는데 시간이 좀 걸릴 것입니다.....

사용자 삽입 이미지

상기 화면과 같이 나타나게 됩니다.. 이것이 바로 어셈블리 소스파일에 대한 설명입니다.
가장상단에서 부터 차근차근 읽어가시기 바랍니다. 내용이 복잡하다구요? 당연합니다..

CPU내부에는 코드세그먼트 / 데이터 세그먼트 / 스택세그먼트 / 익스트라세그먼트 와
여러가지 범용레지스터와 플래그등이 존재합니다. (이런 내용은 Emu8086강좌를 참조하세요)
윈도우에서 실행파일이 실행될려면 원하는 메모리 영역을 할당받아서 그곳의 번호를
인스턴스 핸들이라는 것으로 조절하게 됩니다. 그러한 내용이 표시됩니다.
ImageBase = 00400000h 부분은 어떠한 프로그램이라도 동일 할 것입니다.

MessageBox프로그램은 메뉴도 없고 대화상자도 사용하지 않습니다. 그래서 There Are No~~~
부분이 나타납니다. 실제 프로그램들은 이곳에 정보가 표시됩니다.

중요한것은 "Imported Functions" 부분입니다. Import는 가져오다라는 뜻인데 어디서 가져올까요?
Windows자체에서 가져옵니다. 모든함수들이 Windows\System  or System32 폴더의 dll형태로
존재합니다. dll파일은 함수의 집합체입니다. 윈도우자신도 사용하지만 어셈블리나 다른언어에서도
빌려서 사용할 수 있는것입니다. 이것이 흔히 API라고 부르는 것입니다.

본가이드에서는  user32.dll 과 kernel32.dll에서 가져온 함수들이 있다고 말해줍니다.
user32.dll에서는 MessageBox함수를 가져다 왔고, kernel32.dll에서는 ExitProcess함수를
가져다 썻습니다. 윈도우의 Big3 가 바로 Kernel32.dll / User32.dll / Gdi32.dll입니다.이름만
봐도 무슨함수들의 집합인지 아시겠지요???

바로 밑에는 Import한 함수의 자세한 설명이 나옵니다. 설명안해도 알겠지요?

//***************** Program Entry Point *******************// 부분이 바로 PEP라고
표시되는 프로그램시작 위치 입니다. 무조건 윈도우는 이부분 부터 시작하게 됩니다.
이 위치는 ASM소스코드에서 가장 마지막에 end Start 라고 지정해준 부분이 바로 PEP부분이
되는 것입니다. 이부분부터 순차적으로 명령을 실행합니다.
push 명령을 무지막지하게 사용합니다. 또한 call명령과 jmp명령이 아주 자주나옴을 알수
있을것입니다. 그런데 여기서 필자에게 배신감을 느끼시는 분도 계실것입니다.
asm소스와 동일하다고 해놓고, 하나도 안같네........ ㅎㅎ 끝가지 들어보셔야 합니다.
화면상에서 노란색으로 표시되는 부분을 자세히 보시기 바랍니다. 어디선가 많이 본내용들이지
않습니까?
딱 한줄만 예를 들어서 설명하도록 하겠습니다.

:00401007 6813304000     push 00403013

이것은  메모리주소 / 기계어 / 어셈블리어 순으로 표시되어있는것입니다. 기계어로는 프로그램
을 작성하기 힘들다는이유가 바로 이것입니다. 6813304000 이렇게 작성하면 알턱이 없지요..
이 기계어를 자세히 뜯어보면  x86 cpu가 리틀엔디언이라는 방식이다 라는것을 알아야 이해
할 수 있습니다.  즉 16비트값을 16진수 4자리로 나타내지요?   34AF 라는 16진수를 메모리에
저장할때는 AF34와 같이 낮은주소의 값을 먼저 저장합니다. 34AF로 그대로 저장하는 CPU는
빅엔디언 이라고 합니다. 모토롤라CPU같은것들은 빅엔디언입니다. 왜 이렇게 번거롭게?
했을까요? 아시는 분도 계시겠지만, CPU레지스터는 EAX라는 것은 EAX로 쓰이면 32비트로
사용되고 AX로 쓰이면 16비트 AH / AL 로 사용하면 8비트가 됩니다. 그래서 최하위 AL을
항상 유지시키기 위해서는 리틀엔디언 방식으로 저장해야 하위호환성을 유지할 수 있습니다.
즉 push 명령어는 68  이며 13304000은 리틀엔디언으로 풀면 00403013 입니다. 아시다시피
push는 스택에 넣어라! 뭐를?  00403013을........ 이해되셨나요?

StringData Ref from Data Obj -> "안녕하세요~~~ 입니다" 부분이 표시되네요...
어딘지 아시겠죠? 중간에 깨지는 문자는 ASM소스를 보시면 db 명령으로 선언한 부분입니다.
0DH, 0AH, 00H 등은 화면에 표시할 문자가 없어서 저렇게 나타나는 것입니다.

* Referecnce To : user32.MessageBoxA, Ord: 019Dh
:0040100E E80700000  Call 0040101A

이부분은 멀까요? 바로 user32.dll파일에 포함된 함수인 MessageBoxA함수를 호출하는것입니다.
그래서 call명령어가 나오겠지요...  어셈블리 소스에서는 MessageBox함수를 불렀는데(Invoke)
여기선 끝에 A자가 붙었네요??? 또 속았단 느낌이... -_- ㅎㅎ 함수끝에 A / W 가 붙습니다.
A = Ansi  / W = Wide(UniCode) 라는 의미입니다. 아무것도 안붙이면 자동으로 판별됩니다.
이것은 문자코드에 대해서 장황하게 설명해야합니다. 윈도우2000까지는 Ansi방식입니다.
XP / Vista도 역시 Ansi방식입니다만, 유니코드도 사용가능합니다.... 뭐 안붙이면 자동으로
분별해서 원하는 코드로 맞춰준다만 알아두시기 바랍니다....  즉 함수를 호출할땐 Call로.....
대략 소스가 보이실 겁니다. 윈도우 프로그램은 반드시 ExitProcess로 종료해야합니다. 반드시!!
그부분이 끝부분이 되겠네요......

자 이제는 좀 편하게 해볼까요? "권필진" 이라는 것이 마음에 안든다고 생각합시다.(-_-)
프로그램에서는 보통 "정품을 구입해 주셔서 감사합니다" 겠지요?
"Edit -> Find Text" 혹은 Ctrl  + F 를 눌러 보시기 바랍니다.   뭐 본 가이드에서는 찾고 좌시고
할것도 없습니다. 곧바로 보이죠? 하지만 실제 프로그램에서는 다른 파일에 존재하기도 합니다.
보통 DLL이겠죠.. 어디에서 불려온지를 표시해줍니다. 그부분을 찾아낸다면? 수정도 가능하겠지요?
해당 문자열이 어디에서 호출된지를 알게되면 그부근에서는 분명 메세지박스를표시해주는
함수가 있겠지요? 조금더 위로 가면? 정품이면 어디로 점푸하고 불법이면 어디로 점푸해라는
CMP / JE  / JNE같은 명령어도 있겠네요?? ㅎㅎ 요기까지입니다....

실제로 변경할려면 헥사에디터가 필요합니다. 말그대로 헥사에디터로 로딩해서 찾아서 변경해야
합니다. 생략......

이것보다는 주로 메뉴중에서 "PE Information -> String Data Reference"를 선택해서 주로 사용합니다.
PE Information 메뉴에서 Import부분이나 여러가지 부분은 설명하지 않아도 아실겁니다.

자세한 사용법은 추후로 미루구요.. 마지막으로 간단히  디버깅하는 방법도 살펴보도록 하겠습니다.
"Debug -> Load Process"를 선택하시던지 Ctrl + L 을 실행하시기 바랍니다.
실행파일에 전달할 내용이 있다면 입력하시구요, 대략 없지요.. 그냥  Load 버튼을 누릅니다.
사용자 삽입 이미지

상기화면과 같이 나타나게 됩니다. "Run"버튼을 누르면 뭔가 바삐 움직이면서 역시 실행될 것입니다.
이중에서 하단의 창에서 원하는 정보가 명령을 수행할때마다 한스텝씩 수행해가면서 확인하는것이
바로 디버거 인 것입니다... "Terminate"버튼을 눌러서 종료하면 됩니다.
참고로  Step Into 와 Step Over가 있습니다. 어떤 디버거나 마찬가지입니다. 만약 수행하다가
함수를 만났다면 어찌될까요? MessageBox함수는 윈도우가 제공하는 함수지요? 굳이 내부로 추적
할 필요가 없지요? 그럴때 Step Over를 사용하면 결과만 나타내줍니다. Into로 따라가면 삼천포로
잘빠집니다.... 앞에 Auto가 붙으면 일일이 안해주고 한방에 끝내주고요......


# 작업 04. 마치며

어떻습니까? 어렵지요? 당연히 어렵겠지요.. 하지만 이것이 기본입니다. 낮설어서 어렵게
보이는 것입니다. 익숙해지기 위해서 본가이드가 존재하구요... 글자들이 낮설지 않도록
수시로 눈에 익혀두시기 바랍니다. 계속 보게될 것들이니까요......

본가이드를 벗어나는 방식의 윈도우프로그램은 없습니다. 단지 소스코드의 내용이 많고,
사용하는 변수가 많으며, 파일이 많을 뿐입니다. 어떠한 구조로 작동하는지만 알면,
못따라갈 것이 없겠지요.. 피닉스 바이오스 를 만들고 소스를 공개하지 않아서 리버스엔지니어링
으로 어워드 바이오스가 탄생했다는 속설도 있습니다.... 리버스엔지니어링이 단지 크랙이나
단순한 해킹을 하는 용도가 아님을 아실수 있을것입니다. 윈도우도 다시 만들수 있고,
윈도우가 하는 모든것을 다시 할 수 있습니다. 아무리 복잡한 잠금도 역으로 풀수도 있겠네요.

자 이제 여러분은 배울것이 많아졌습니다. 하지만 무언가를 배운다는 느낌이 들것입니다.
저는 그랬으니까요.. 아 이건가? 하고 느끼게 되기까지 5년이 걸렸었으니까요...
여러분들은 그기간을 확 줄일 수 있을것입니다. 도스와는 차원이 다른 배우는 맛이있는
윈도우프로그래밍이 있으니까요.... 그후에 C를 보시고 VB / Delphi / C# 등을 보시기바랍니다.
편하네! 외엔.... 어떠한 강력함도 못느끼시게 될테니까요......

Posted by openserver