레지스터
Register는 CPU 내부에 존재하는 다목적 저장 공간이다.
이름 | 크기 (bit) | 용도 | |
범용 레지스터 | EAX | 32 | 주로 산술 연산/함수 결괏값 저장 |
EBX | 32 | 특정 주소 저장 (함수 호출 시 ESP 값) | |
ECX | 32 | 반복 횟수 저장 | |
EDX | 32 | 일반 자료 저장 | |
세그먼트 레지스터 | CS | 16 | 코드 세그먼트 |
SS | 16 | 스택 세그먼트 | |
DS | 16 | 데이터 세그먼트 | |
프로그램 상태와 컨트롤 레지스터 | EFLAGS | 32 | ZF, OF, CF 등 상태 표시 |
Instruction Pointer | EIP | 32 | CPU가 처리할 명령어의 주소를 나타냄 |
어셈블리어
1. 비트연산 : shift 연산
1) 부호가 없는 연산
- 왼쪽으로 이동 : shl
- 오른쪽으로 이동 : shr
2) 부호가 있는 연산 (MSB를 유지)
- 왼쪽으로 이동 : sal
- 오른쪽으로 이동 : sar
2. 제어
명령 | 설명 | 사용 예 |
cmp | 두 개의 오퍼랜드 비교 (뺄셈 연산 후 플래그 설정) | cmp ecx, 0 |
test | 두 개의 오퍼랜드 비교 (AND 연산을 수행 후 플래그 설정) | test eax, eax |
call | 해당되는 주소의 함수를 호출하여 수행 코드 위치를 옮김 | call 0x12345678 |
int | 오퍼랜드로 지정된 예외 처리 수행 (0xcd) 중단점으로 디버그용 소프트웨어 트랩 (0xcc) 오버플로우 예외 상황시 발생하는 트랩 (0xce) 하드웨어 디버그 트랩 (0x90) |
int 3 int3 int0 int1 |
leave | 함수에서 사용한 지역변수 스택을 비움 | leave |
ret | 스택에서 저장된 주소로 복귀 | ret |
nop | 아무 동작도 수행하지 않음 | nop |
3. 분기
명령어 | 설명 | |
CALL | Call | 프로시저 호출 |
JMP | Unconditional Jump | 무조건 분기 |
RET | Return from CALL | CALL로 스택에 PUSH된 주소로 복귀 |
JE/JZ | Jump on Equal / Zero | 결과가 0이면 분기 |
JL/JNGE | Jump on Less / not Greater or Equal | 결과가 작으면 분기 (부호화된 수) |
JB/JNAE | Jump on Below / not Above or Equal | 결과가 작으면 분기 (부호화 안 된 수) |
JBE/JNA | Jump on Below or Equal / not Above | 결과가 작거나 같으면 분기 (부호화 안 된 수) |
JP/JPE | Jump on Parity / Parity Even | 패리티 플레그가 1이면 분기 |
JO | Jump on Overflow | 오버플로가 발생하면 분기 |
JS | Jump on Sign | 부호 플레그가 1이면 분기 |
JNE/JNZ | Jump on not Equal / not Zero | 결과가 0이 아니면 분기 |
JNL/JGE | Jump on not Less / Greater or Equal | 결과가 크거나 같으면 분기 (부호화된 수) |
JNLE/JG | Jump on not Less or Equal / Greater | 결과가 크면 분기 (부호화된 수) |
JNB/JAE | Jump on not Below / Above or Equal | 결과가 크거나 같으면 분기 (부호화 안 된 수) |
JNBE/JA | Jump on not Below or Equal / Above | 결과가 크면 분기 (부호화 안 된 수) |
JNP/JPO | Jump on not Parity / Parity odd | 패리티 플레그가 0이면 분기 |
JNO | Jump on not Overflow | 오버플로우가 아닌 경우 분기 |
JNS | Jump on not Sign | 부호 플레그가 0이면 분기 |
LOOP | Loop CX times | CX를 1감소하면서 0이 될 때까지 지정된 라벨로 분기 |
LOOPZ/LOOPE | Loop while Zero / Equal | 제로 플레그가 1이고 CX≠0이면 지정된 라벨로 분기 |
LOOPNZ/LOOPNE | Loop while not Zero / not Equal | 제로 플레그가 0이고 CX≠0이면 지정된 라벨로 분기 |
JCXZ | Jump on CX Zero | CX가 0이면 분기 |
INT | Interrupt | 인터럽트 실행 |
INTO | Interrupt on Overflow | 오버플로우가 발생하면 인터럽트 실행 |
IRET | Interrupt Return | 인터럽트 복귀 (리턴) |
4. 반복
mov ecx, 반복 횟수
라벨 :
반복 내용
loop 라벨
디버거 설치 및 사용방법
- With Hello, Would! 디버깅
1. 프로그램 옵션 설정 사항
빌드 -> 구성 관리자 -> Release
프로젝트 -> HelloWorld 속성 -> 링커 -> 고급 -> 임의 기준 주소 -> 아니요 (/DYNAMICBASE:NO)
2. 빌드 -> 일괄 빌드
응용 프로그램을 다운받은 Immunity Debugger의 텅 빈 검은 4분할 화면으로 드래그해준다.
Immunity Debugger 다운로드 :
https://www.immunityinc.com/products/debugger/
제 1사분면 : Register window : 레지스터가 어떻게 변하는지 볼 수 있다.
제 2사분면 : Code window : 코드 주소 -> 어셈블리어 -> 주석 순으로 볼 수 있다.
제 3사분면 : Dump window : 코드 주소, 헥사 코드, 아스키 코드를 볼 수 있다.
제 4사분면 : Stack window : 함수를 실행하면 stack에서 실행 중인 함수의 변화를 관찰할 수 있고 함수가 종료되면 초기화된다.
Ctrl + F2 : 다시 처음부터 디버깅 시작 (Restart)
EP (Entry Point) : Windows 실행 파일(exe)의 코드 시작점
(실습에서는 아래와 같다.)
제 2사분면 - 코드 주소 -> 어셈블리어 -> 주석 순으로 볼 수 있다.
CALL HelloWor.wmain 이 메인함수이다.
main() 함수에는 MessageBoxW() API 를 호출하는 코드가 있다.
F7 (Step Into) 명령어로 CALL 의 함수 안으로 따라들어갈 수 있다.
CALL : 특정 주소의 함수를 호출하는 명령어
JMP : 특정 주소로 점프하는 명령어
RETN : 스택에 저장된 복귀 주소로 점프하는 명령어
F2 : BP (Break Point) 설정
F9 : BP 까지 실행
Space bar : 명령어 수정
제 1사분면 - 레지스터가 어떻게 변하는지 볼 수 있다.
제 3사분면 - 코드 주소, 헥사 코드, 아스키 코드를 볼 수 있다.
제 4사분면 - 함수를 실행하면 stack에서 실행 중인 함수의 변화를 관찰할 수 있고 함수가 종료되면 초기화된다.
'REVERSING' 카테고리의 다른 글
[SWING] Reversing 08 (0) | 2023.04.30 |
---|---|
[SWING] Reversing 07 (0) | 2023.04.02 |
[SWING] Reversing 05 (0) | 2022.08.26 |
[SWING] Reversing 04 (0) | 2022.08.22 |
[SWING] Reversing 03 (0) | 2022.08.13 |