jam 블로그

[이론] 리버싱시 알아두면 좋을 어셈블리어(리버스엔지니어링 역분석 구조와 원리 발췌) 본문

해킹/리버싱 & 악성코드

[이론] 리버싱시 알아두면 좋을 어셈블리어(리버스엔지니어링 역분석 구조와 원리 발췌)

kid1412 2009. 11. 28. 14:59
728x90

1) CPU 레지스터

1> 범용 레지스터
EAX : 곱셈과 나눗셈 명령에서 자동으로 사용되고 함수의 리턴값이 저장되는 용로도로 사용된다.
EBX : ESI나 EDI와 결합하여 인덱스에 사용된다.
ECX : 반복 명령어 사용시 반복 카운터로 사용된다. ECX 레지스터에 반복할 횟수를 지정해 놓고 반복 작업을 수행하게 한다.
EDX : EAX와 같이 쓰이며 부호 확장 명령 등에 쓰인다.
ESI : 데이터 복사나 조작시 Source Data의 주소가 저장된다. ESI 레지스터가 가리키는 주소의 데이터를 EDI 레지스터가 가리키는 주소로 복사하는 용도로 많이 사용된다.
EDI : 복사 작업시 Destination의 주소가 저장된다. 주로 ESO 레지스터가 가리키는 주소의 데이터가 복사된다.
ESP : 하나의 스택 프레임의 끝 지점 주소가 저장된다. PUSH, POP 명령어에 따라서 ESP의 값이 4Byte씩 변한다.
EBP : 하나의 스택 프레임의 시작 지점 주소가 저장된다. 현재 사용되는 스택 프레임이 소멸되지 않는 동안 EBP의 값은 변하지 않는다. 현재의 스택 프레임이 소멸되면 이전에 사용되던 스택 프레임을 가리키게 된다.

2> 명령 포인터
EIP : 다음에 실행해야 할 명령어가 존재하는 메모리 주소가 저장된다. 현재 명령어를 실행 완료한 후에 EIP 레지스터에 저장되어 있는 주소에 위치한 명령어를 실행하게 된다. 실행 전 EIP 레지스터에는 다음 실행해야 할 명령어가 존재하는 주소의 값이 저장된다.

3> 세그먼트 레지스터
CS : 실행 가능한 명령어가 존재하는 세그먼트의 오프셋이 저장된다.
DS : 프로그램에서 사용되는 데이터가 존재하는 세그먼트의 오프셋이 저장된다.
SS : 스택이 존재하는 세그먼트의 오프셋이 저장된다.

4> 플래그 레지스터
CF : 부호 없는 연산 결과가 용량보다 클 때 세트(1)된다.
ZF : 연산 결과가 0일 때 세트(1)된다. 연산 결과가 0이 아닐 때 해제(0)된다.
OF : 부호 있는 연산 결과가 용량보다 클 때 세트(1)된다.
SF : 연산 결과가 음수가 되었을 때 세트(1)된다. 연산 결과가 양수가 되었을 때 해제(0)된다.
DF : 문자열 처리에서 연속되는 문자열의 처리 방향에 따라 세트된다.

2) 어셈블리 명령어

INC : 피연산자에 1을 더한다.
DEC : 피연산자에 1을 뺀다.
ADD : Destination(D로 통칭)에 Source(S로 통칭)의 값을 더해서 Destination에 저장.(형태 : ADD D,S)
SUB : D에 S의 값을 빼서 D에 저장.(형태 : SUB D, S)
MUL : 부호 없는 al, ax, eax의 값을 피연산자와 곱한다. 피연산자가 8비트이면 al과 곱해서 ax에 저장 16비트이면 ax와 곱하고 dx:ax에 저장 (형태 : MUL reg)
IMUL : 부호 있는 al,ax,eax의 값을 피연산자와 곱한다.
단일 피연산자이고 피연산자를 al,ax,eax에 곱한다. (형태 : IMUL r/m)
value를 al,ax,eax와 곱해서 D에 저장한다. (형태 : IMUL D, V)
value끼리 곱해서 D에 저장한다. (형태 : IMUL D, V, V)
DIV : 8, 16, 32비트 부호 없는 정수의 나눗셈을 수행 (형태 : DIV reg)
MOV : S에서 D으로 데이터를 복사 (형태 : MOV D, S)
MOVS : S에서 D으로 데이터를 복사. (형태 : MOVS D,S)
MOVSB, MOVSW, MOVSD : SI 또는 ESI 레지스터에 의해 지정된 메모리 주소의 내용을 DI 또는 EDI 레지스터에 의해 지정되는 메모리 주소로 복사.
MOVSB : Byte 단위로 복사
MOVSW : Word 단위로 복사
MOVSD : Dword 단위로 복사
MOVSX : Byte나 Word 크기의 피연산자를 Word나 Dword 크기로 확장하고 부호는 그대로 유지.
MOVZX : Byte나 Word 크기의 피연산자를 Word나 Dword 크기로 확장하고 남은 비트는 0으로 채운다.
INT : 소프트웨어 인터럽트를 발생시켜 운영체제의 서브루틴을 호출한다.
AND : D와 S 피연산자의 각 비트가 AND 연산된다.
OR : D와 S 피연산자의 각 비트가 OR 연산된다.
XOR : D와 S 피연산자의 각 비트가 XOR 연산된다.
TEST : 두 피연산자 사이에 논리적인 AND 연산을 수행하여 플래그 레지스터에 영향을 주지만 결과값은 저장하지 않는다. OF, CF는 항상 0으로 세트, TEST 연산 결과값이 0이면 ZF가 1, 0이 아니면 ZF가 0으로 세트된다.
STC : 캐리 플래그(CF)를 1로 세트한다.
CLC : 캐리 플레그를 0으로 세트한다.
STD : 방향 플래그(DF)를 1로 세트한다.
CLD : 방향플래그를 0으로 세트한다.
STI : 인터럽트 플래그(IF)를 1로 세트한다.
CLI : 인터럽트 플래그(IF)를 0로 세트한다.
SHL : D 피연산자를 S 피연산자의 크기만큼 왼쪽으로 각 비트를 시프트시킨다. 최상위 비트는 CF로 복사된다. 최하위 비트는 0으로 채워진다.
SHR : D 피연산자를 S 피연산자의 크기만큼 오른쪽으로 각 비트를 시프트시킨다. 최상위 비트는 0으로 최하위 비트는 CF로 복사된다.
PUSH : 스택에 값을 넣는다.
PUSHAD : EAX, EBX, ECX, EDX, ESI, EDI, ESP, EBP 레지스터의 값을 스택에 PUSH 한다.
PUSHFD : 플래그 레지스터를 스택에 PUSH한다.
POP : ESP 레지스터가 가리키고 ㅣㅇㅆ는 위치의 스택공간에서 4바이트 만큼 D 피연산자에복사하고 ESP 레지스터의 값에 4를 더한다.
POPAD : 스택에 존재하는 값을 EAX, EBX, ECX, EDX, ESI, EDI, ESP, EBP 레지스터로 POP한다. 스택에 보관해 놓은 레지스터 정보를 다시 애용하려고 할 때 사용됨.
POPFD : 스택에 존재하는 값을 플래그 레지스터로 POP한다.
XCHG : 두 피연산자의 내용이 서로 교환된다.
NEG : 피연산자의 2의 보수를 계산하여 결과를 피연산자에 저장한다.
PTR : 피연산자의 크기를 재설정한다.
OFFSET : 세그먼트의 시작으로부터 변수가 위치한 거리까지의 상대적 거리를 리턴한다.
LEA : S 피연산자의 유효 주소를 계산하여 D 피연산자에 복사한다.
REP : ECX 레지스터를 카운터로 사용해서 문자열 관련 명령을 ECS >0인 동안 반복한다.
JMP : 피연산자가 가리키는 코드로 점프 뛰어서 실행한다.
CALL : 함수 호출시 사용된다.
CMP : 두 피연산자를 비교하는 작업을 한다. 값이 같으면 0되고 ZF가 1로 세트 다르면 ZF가 0으로 세트된다.
NOP : 아무 일도 하지 않는 명령어이다.
Comments