반응형

CMOVcc (Conditional Move) 명령어를 사용해 보자.

 

CMOVE - 같으면(ZF=1) 이동한다.

 

CMOVNE - 같지 않으면(ZF=0) 이동한다.

 

eax와 ebx가 같지 않기 때문에 ecx에 eax 값 1이 저장된다.

 

eax와 ebx가 같지 않기 때문에 ecx에 eax 값 1이 저장되지 않는다.

 

반응형
Posted by J-sean
:
반응형

Intel® 64 and IA-32 Architectures Software Developer’s Manual을 확인해 보자.

 

 

RDTSC—Read Time-Stamp Counter

Reads the current value of the processor’s time-stamp counter (a 64-bit MSR) into the EDX:EAX registers. The EDX register is loaded with the high-order 32 bits of the MSR and the EAX register is loaded with the low-order 32 bits. (On processors that support the Intel 64 architecture, the high-order 32 bits of each of RAX and RDX are cleared.) The processor monotonically increments the time-stamp counter MSR every clock cycle and resets it to 0 whenever the processor is reset.

RDTSC 인스트럭션은 프로세서의 time-stamp counter를 EDX:EAX 레지스터로 가져온다. EDX에는 상위 32비트가 저장되고 EAX에는 하위 32비트가 저장된다.

 

EDX, EAX에 저장되는 값을 확인해 보자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
%include "io64.inc"
 
section .text
global CMAIN
CMAIN:
    rdtsc
 
    PRINT_STRING 'High-order 32 bits of Time Stamp Counter: '
    PRINT_HEX 4, edx
    NEWLINE
    NEWLINE
    
    PRINT_STRING 'Low-order 32 bits of Time Stamp Counter: '
    PRINT_HEX 4, eax
    NEWLINE
    NEWLINE
    
    PRINT_STRING 'Time Stamp Counter: '    
    shl rdx, 32
    xor rdx, rax
    PRINT_HEX 8, rdx
 
    xor rax, rax
   ret
 

 

 

EDX, EAX의 값을 확인한다.

 

EAX 레지스터에 저장된 값을 이용해 1~10까지의 랜덤 넘버를 추출해 보자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
%include "io64.inc"
 
section .text
global CMAIN
CMAIN:
    rdtsc
    
    ;eax에 저장되는 값을 사용한다.
    PRINT_STRING 'Low-order 32 bits of Time Stamp Counter (dividend): '
    PRINT_HEX 4, eax
    NEWLINE
    NEWLINE
    
    ;2byte 이상 나누기 연산시 div 는 dx, ax를 사용한다.
    ;나누어지는 값을 dx:ax에 나누어 삽입해야 하므로 edx를 0으로 만들고 eax의
    ;값 중 2바이트만 사용한다.
    xor edx, edx
    and eax, 0x0000ffff
    PRINT_STRING 'DX: '
    PRINT_HEX 2, dx
    NEWLINE
    PRINT_STRING 'AX: '
    PRINT_HEX 2, ax
    NEWLINE
    NEWLINE
    
    mov bx, 0xa ;나누는 수를 10으로 설정한다.
    PRINT_STRING 'Divisor: '
    PRINT_HEX 2, bx
    NEWLINE
        
    div bx ;bx(10)로 나눈다. 나머지는 0~9가 나온다.
    PRINT_STRING 'Quotient: '
    PRINT_HEX 2, ax ;몫은 ax에 저장된다.
    NEWLINE
    PRINT_STRING 'Remainder: '
    inc dx
    ;나머지는 dx에 저장된다. 1을 더해서 범위를 1~10으로 맞춘다.
    PRINT_HEX 2, dx
    
    xor rax, rax
   ret
 

 

 

 

Remainder로 1~10의 숫자가 무작위로 추출된다.

 

그런데 실제로 여러번 해 보면 홀수만 나오는 것을 알 수 있다. 내 컴퓨터에서만 그러는건지는 모르겠지만 rdtsc 명령어가 (EAX 레지스터에)짝수만 반환하기 때문이다. (마지막에 1을 더하므로 결국 홀수가 된다)

 

EDX 레지스터의 값을 사용해 보자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
%include "io64.inc"
 
section .text
global CMAIN
CMAIN:
    rdtsc
    
    ;edx에 저장되는 값을 사용한다.
    PRINT_STRING 'High-order 32 bits of Time Stamp Counter (dividend): '
    PRINT_HEX 4, edx
    NEWLINE
    NEWLINE
    
    ;2byte 이상 나누기 연산시 div 는 dx, ax를 사용한다.
    ;나누어지는 값을 dx:ax에 나누어 삽입해야 하므로 edx의 값을 eax에 저장하고
    ;edx를 0으로 만든다. 그리고 eax의 값 중 2바이트만 사용한다.
    mov eax, edx    
    xor edx, edx
    and eax, 0x0000ffff
    PRINT_STRING 'DX: '
    PRINT_HEX 2, dx
    NEWLINE
    PRINT_STRING 'AX: '
    PRINT_HEX 2, ax
    NEWLINE
    NEWLINE
    
    mov bx, 0xa ;
    PRINT_STRING 'Divisor: '
    PRINT_HEX 2, bx
    NEWLINE
        
    div bx
    PRINT_STRING 'Quotient: '
    PRINT_HEX 2, ax
    NEWLINE
    PRINT_STRING 'Remainder: '
    inc dx
    PRINT_HEX 2, dx
 
    xor rax, rax
   ret
 

 

 

홀수, 짝수 상관없이 1~10의 숫자가 무작위로 추출된다.

하지만 EDX 레지스터의 값은 일반적인 시간의 '초' 단위와 비슷한 간격으로 바뀐다. 프로그램을 빠르게 반복 실행하면 동일한 숫자가 반복되어 나오는걸 알 수 있다. 빠른 반복 추출이 필요하다면 EAX 레지스터의 값 중 하위 2바이트가 아닌 중간 2바이트 숫자를 이용하는 등 다른 방법으로 랜덤 넘버를 추출한다.

 

※ 주의

DIV 연산시 나누는 수가 작아 몫이 너무 크게 되면 ax가 저장할 수 있는 용량(2바이트)을 넘어서게 되고 Program received signal SIGFPE, arithmetic exception 메세지가 나타난다. Floating-Point Exception을 의미하지만 0으로 나누는 연산과 같은 모든 산술 연산 에러를 포함한다.

Program Error Signals

 

SIGFPE 예외 발생시 프로그램이 멈추게 된다. 디버깅해야 메세지를 확인 할 수 있다.

 

반응형
Posted by J-sean
:
반응형

emu8086은 80~90년대 사용되던 8086 프로세서 에뮬레이터다. 이게 왜 필요할까? 

 

 

요즘은 어셈블리어에 대한 사람들의 관심이 거의 없다 보니 자료를 찾아도 예전 도스(DOS) 시절 만들어진 자료가 대부분이다. 물론 그런 자료도 참고 할 수는 있지만 컴퓨팅 환경이 그때와는 너무 많이 달라져서 그런 책이나 자료로 실습은 불가능한 상황이다. 그래서 예전 환경을 에뮬레이팅 해 주는 EMU8086이 필요한 것이다.

 

좀 불편하긴 해도 도스(DOS) 에뮬레이터 도스박스(DOSBox)를 사용하면 8086 프로세서 어셈블리 프로그래밍을 연습할 수 있다.

 

2022.12.16 - [Reverse Engineering] - MASM 6.11

 

우리는 emu8086을 사용해 보자.

 

emu8086.zip
2.99MB

 

 

emu8086의 Hello, World! 예제. 소스를 실행해 보고 싶다면 emulate를 클릭한다.

 

에뮬레이트할 소스 코드를 보여주는 창. 첫 번째 명령어에서 실행 대기 상태가 된다.

 

에뮬레이터에서는 메모리 주소와 기계어 코드, 레지스터 상태를 확인할 수 있고 디버거, 버추얼 디바이스등 여러가지 기능을 사용할 수 있다.

 

Hello, World! 예제 실행 화면.

 

 

help 버튼을 클릭하면 Tutorial, Instruction Set, Interrupt등 여러가지 설명을 확인할 수 있다.

 

emu8086은 14일간 무료로 사용할 수 있는 shareware다. 그런데 홈페이지도 없어진거 같고.. 더 이상 개발이 진행되는거 같지가 않다. 구매가 가능한지도 모르겠다. 그렇다면.. Registration Key는 알아서 구한다.

 

원한다면 리버싱으로 직접 등록키를 알아낼 수도 있다. 참고로 등록키 암호화에 사용된 문자열은 JKASERKKN837C3FRTQZX이고..

 

Visual Basic으로 만들어졌다.

 

리버싱에 성공한다면 이렇게 자신의 이름을 직접 등록할 수 있다.

 

반응형
Posted by J-sean
:
반응형

C/C++로 작성한 코드를 어셈블리어로 번역해 보자.

 

C/C++ 소스를 작성한다.

 

Solution Explorer - Source File - 우클릭 - Properties

 

Assembler Output - Assembly-Only Listing (/FA)를 선택한다.

Assembly-Only Listing: 어셈블리어만 출력한다.

Assembly With Machine Code: 어셈블리어와 기계어 코드를 출력한다.

Assembly With Source Code: 어셈블리러와 소스 코드를 출력한다.

Assembly, Machine Code and Source: 어셈블리, 기계어 코드 그리고 소스코드를 출력한다.

 

 

프로젝트를 빌드하면 어셈블리 파일이 생성된다.

 

C/C++ 소스 코드가 어셈블리어로 변환되었다.

 

반응형
Posted by J-sean
:

MASM 6.11

Assembly 2022. 12. 16. 15:31 |
반응형

DOS에서 실행 가능한 마지막 MASM 버전 6.11

 

 

masm611.zip
11.29MB

문서 포함

 

Microsoft Macro Assembler 6.11.zip
7.03MB

3.5인치 플로피 디스크 IMG 파일

 

반응형
Posted by J-sean
: