4-1공부/리버스엔지니어링
[중간고사] asm1
KGW2027
2023. 4. 16. 00:22
728x90
반응형
x32dbg를 이용한 32-bit 예제 프로그램에 대한 디버깅 및 C코드 추론 작업에 대해 학습함.
1. 어셈블리에 포함된 security_cookie는 Array/Struct가 Buffer-Overflow 되었을 때, 그걸 감지하기 위해 있다.
2. 함수에 파라미터를 입력할 때 or 값을 저장할 때, endian에 의해 값이 거꾸로 저장된다.
참조(주소) 형식
- 'size' ptr 'ss/ds':['addr']
: size는 데이터의 크기를 의미하는 것으로, byte(1-byte), dword(2-byte), qword(4-byte)가 있다.
: ss는 Stack Segment로 지역변수와 같은 스택/힙 영역, ds는 Data Segment로 전역변수와 같은 데이터 영역에 저장한다.
: addr는 해당 size,ss로 가리키는 곳이 어디인지에 대한 것으로, 메모리 주소에 대해 하드코딩 될수도 있고, ebp 와 같은 레지스터를 이용해 상대주소로 사용될 수도 있다.
레지스터의 종류
레지스터 이름 | 영어명 | 역할 |
ebp | Base Pointer | 현재 함수의 스택 시작 위치를 가리킨다. |
esp | Stack Pointer | 현재 함수의 스택 최상단(다음 Push 위치)를 가리킨다. |
eax | Accmulator Register | 산술연산을 수행하거나, 함수의 반환값이 저장된다. |
ecx | Counter Register | 카운터 레지스터 |
eip | Instruction Pointer | 다음에 실행될 명령어가 저장된다. |
ST(i), xmm | 부동 소수점 연산에 사용되는 레지스터다. |
어셈블리 명령어
명령어 | 설명 |
mov 'addr', 'value' | 어떤 주소에 값을 입력한다. 보통 상수 변수 선언 등에 자주 사용된다. |
mov 'reg', 'value' | 어떤 레지스터에 값을 입력한다. 보통 Mem2Mem 전송이나, 함수 호출(스택 push)등을 위해 중간에 거쳐가는 용도로 자주 사용된다. |
lea 'reg', 'ptr' | 레지스터에 포인터 값을 입력한다. 예를 들어, 정수형 a가 있을 때, int* b = &a는 lea eax, 'a의 주소' mov 'b의 주소', eax 같은 식으로 사용된다. |
xor eax, eax | 자기 자신에 xor하면 0이 나온다는 것을 이용한 최적화 기법이다. 보통 return 0에서 자주 보인다. |
cmp r1, r2 | r1과 r2가 같은지 subtract를 이용해 확인한다. 이 때 r1, r2의 값에는 변경이 일어나지 않는다. |
test eax, eax | 자기 자신에 and를 걸어 0인지 아닌지를 확인한다. 보통 if + jmp 용도로 많이 쓰인다고 한다. |
push ebp, pop ebp | push를 통해 스택에 ebp값을 넣고, pop을 통해 스택의 값을 ebp에 넣는다. |
main asm 예시
# 함수 시작
push ebp // 이전 함수의 ebp 스택에 저장
mov ebp, esp // 현재 스택 위치를 ebp에 저장. (현재 함수의 시작 위치)
# 지역 변수 할당
sub esp, N // N-byte의 공간을 미리 확보, 매 변수를 push로 할 수 있으나, 최적화 기법임
mov dword ptr ss:[ebp-a], val // ebp에서 a-byte 내려온 위치에 val 입력. (변수 x)
lea eax, dword ptr ss:[ebp-a] // eax에 주소값 저장
mov dword ptr ss:[ebp-b], eax // 변수 y에 x의 주소값 저장
# 함수 호출
call <program._func> // func 함수를 호출한다.
# 함수 종료
xor eax, eax // return 0을 위해 eax를 0으로 세팅한다.
mov esp, ebp // 스택 위치를 초기 위치로 돌려보낸다.
pop ebp // ebp에 이전 함수의 ebp를 입력한다.
ret // ebp와 eip를 이용해 이전 함수로 돌아간다.
728x90
반응형