tuts4you
프로그램
- reverseMe
이것은 무슨 파일인가?
- ARTeam-Ollydbg.ini → 이것은 ollydbg.ini로 덮기
- Win32.hlp fil : 프로그램에서 작동하는 API 이해 도움 (API 정보를 알려줌)
- 이렇게 추가 가능 (Select ~ )
![](https://raw.githubusercontent.com/seleuchel/blog/559eab4ba7b9f45e34dbbb087e9511bc5bad87a2/Mal/LENA/1/Untitled.png)
올리는 뭐야
- 디버거
올리의 기본 정보
- UDD : Breakpoints와 다른 정보들을 저장
- Plugin : 올리의 플러그인들
![](https://raw.githubusercontent.com/seleuchel/blog/559eab4ba7b9f45e34dbbb087e9511bc5bad87a2/Mal/LENA/1/Untitled%201.png)
올리의 첫 화면
올리의 화면 구성요소
- CPU : CPU가 현재 어떤 명령을 수행하는지 가리킴 (PC). 주소, 어셈블리어, OP코드, 주석이 있다.
- 메모리 : 가상메모리의 값. 메모리의 데이터 확인 가능
- 레지스터 : 레지스터의 값. 항상 16진수이다.
- 스택(LIFO) : 스택에 쌓인 값을 볼 수 있다. ESP, EBP 기준으로 보는 것도 가능함
- Pane window : CPU 아래에 있는 작은 창. 명령에 대한 구체적인 설명을 보여줌.
- (EX. 변수 a가 정수 10을 담고 있고, EIP(다음 명령을 가리키는 포인터)가 변수 a와 12를 비교하는 명령을 담고 있는 경우, “10과 12를 비교해서 10이 더 작음” 이라는 내용을 보여줌)
- 상태창 : 올리 맨 아래에 있는 창. 실행 여부, Break Point 여부 등 진행 상태를 나타냄
- LEMTWHC/KBR...S
- Log data
- Executable modules
- Memory
- Threads
- Windows
- Handles
- Cpu
- / : Patches
- K : Call stack of main thread
- Break points
- References
- ... : Run trace
- Source
자료형 사이즈 (컴구 내용) [32bit 기준]
- 1 byte = 2 digits
- 1 byte = 8 bit
- 1 words = 2 bytes
- 1 dward = 2 words = 4 bytes
레지스터의 정보
- eax : Extended Accumulator Register
- 산술 연산. 결과값 저장에 주로 사용(return 값)
- 16bit : AX
- 8bit : AH/AL
- ebx : Extended Base Register
- DS 세그먼트에서 데이터 가리킬 때 주로 사용
- 16bit : BX
- 8bit : BH/BL
- ecx : Extended Counter Register
- 반복문에서 주로 사용 (반복 돌 때마다 COUNT를 계산하며, COUNT는 1씩 내려간다)
- 16bit : CX
- 8bit : CH/CL
- edx : Extended Data Register
- 데이터를 가리키는 레지스터
- 16bit : DX
- 8bit : DH/DL
- esi : Extended Source Index
- 데이터를 복사/이동 시, src(출발지) 주소 가리킴
- 16bit : SI
- edi: Extended Destination Index
- 데이터를 복사/이동 시, dst(도착지) 주소 가리킴
- 16bit : DI
- ebp : Extended Base Pointer
- 스택의 base pointer. 스택의 바닥(스택은 위에서 아래로 내려가므로, 진행되는 함수가 사용하는 스택의 맨 윗 부분이라고 할 수 있음[가장 높은 주소]). 스택 프레임의 기준.
- 현재 진행하는 함수를 호출한 이전 함수의 EBP를 담음
- 16bit : BP
- esp : Extended Stack Pointer
- 스택의 stack pointer. 스택의 상위(스택은 위에서 아래로 내려가므로, 진행되는 함수가 사용하는 스택의 맨 아랫부분이라고 할 수 있음[가장 낮은 주소 or 연산을 위해 막 쓰고자 하는 주소]). 스택이 사용되는 위치를 가리킴.
- 16bit : SP
- eip : Extended Instruction Pointer
- PC(Process Counter). 다음 CPU가 진행할 명령어를 가리키는 포인터
- 16bit : IP
EX) 7c 90 01 95
edx = 7c900195
dx = 0195
dh = 01
dl = 94
기타 단축키
- 명령 하나씩 진행 : F8
- 명령 하나씩 진행 (깊게 들어감) : F7
- 만약, CALL 하는 명령어에서 F7 누르면, CALL 하는 함수로 이동하여 하나씩 진행됨
- BP 걸기 : F2
- 다시 프로그램 실행 : CTRL + F2
- 주석 : /
- 다음 BP까지 다 실행 : F9
- 이동 (주소 점프) : ctrl + g
어셈블리어
- OPCODE OPERAND 형태이다. (EX. PUSH EAX)
- 명령에따라 여러개의 OPERAND가 존재할 수 있다.
기본 어셈 명령
- PUSH : 스택에 데이터를 넣는다.
- PUSH A : A(아마도 레지 OR 메모리)에 있는 데이터 OR A라는 값을 스택에 넣음. 이후 ESP는 여길 가리킴
- POP : 스택에 데이터를 뺀다 (ESP 기준)
- POP : 스택 ESP가 가리키는 데이터를 뺀다.
- POP A : 스택 ESP가 가리키는 데이터를 빼어, A에 저장
- MOV : 데이터 복사
- MOV A B : B에 있는 데이터를 A에 저장
- MOVS,MOVSB,MOVSW,MOVSD ESI, EDI
- Byte/word/dword ESI points에서 EDI 공간에 값을 복사
- MOVSX : Bytes나 Word에서 Word나 Dword 크기로 확장. 부호 유지
- MOVZX : Bytes나 Word에서 Word나 Dword 크기로 확장. 빈영역은 0으로 채우기
- CALL : 함수 호출
- CALL A : A라는 함수를 호출한다. 보통 A에는 함수의 가상주소가 들어간다.
- JMP : EIP 이동
- JMP A : A가 가리키는 위치(OR 주소)로 EIP를 이동한다.
- JNZ : ZF = 0 가 아니면 점프
- CALL VS JMP
- CALL은 CALL을 호출하는 함수의 EBP를 스택에 저장한 뒤, CALL로 호출된 함수의 명령으로 이동(JMP)한다.
- JMP는 바로 JMP로 호출된 위치로 이동한다.
- CMP : 값 비교
- CMP A , B : B와 A의 값을 비교한다. 그에따른 플래그를 결정한다. (Carry-flat, Overflow-flag, Zero-flag)
- Zero-flag : A, B가 같으면 이게 1이된다.
- CMP A , B : B와 A의 값을 비교한다. 그에따른 플래그를 결정한다. (Carry-flat, Overflow-flag, Zero-flag)
- TEST : 논리 AND
- TEST A, B : 거의 TEST EAX EAX인 경우가 많다. ⇒ EAX가 0이면 1, 아니면 0이다.
- 연산의 데이터를 저장하지 않는다.
- AND : 논리 AND
- OF와 CF를 클리어하고, ZF를 set(1) 한다
- TEST VS AND?
- ?
- XOR : 배타적 논리 OR 연산
- OF와 CF를 CLEAR하고, ZF를 SET 한다.
- XOR A, A 는 항상 0
프롤로그 / 에필로그
- 프롤로그 : 스택프레임의 시작을 나타냄
이전 함수의 EBP를 저장하고, EBP를 ESP위치(새로운 EBP 위치임. 이전함수의 EBP가 저장된 위치)로 이동
[일반적인 형태]
- PUSH EBP
- MOV EBP, ESP
- 에필로그 : 스택프레임의 종료를 나타냄
이전 함수의 EBP를 되돌리고, 종료할 함수가 호출된 이전 함수 명령 위치의 다음 명령을 가리킴
[일반적인 형태]
- LEAVE
- RET
이후에는 스택의 데이터를 정리 등 (호출 방식(?)에 따라 다름)
CALL의 형태
- CALL 404000 (CALL address)
- CALL EAX (CALL register - executes the procedure with address == value of EAX)
- CALL DWORD PTR [EAX] executes procedure at address with value of EAX
- CALL DWORD PTR [EAX+5] executes procedure at address with value of EAX+5
- CALL <JMP to API> is in fact also a CALL address, but it's kind of special because it executes an API (see further)
ㄴ 이거는 API를 실행할 수 있음을 나타낸다.
분석하기
- Run 실행 결과
![](https://raw.githubusercontent.com/seleuchel/blog/559eab4ba7b9f45e34dbbb087e9511bc5bad87a2/Mal/LENA/1/Untitled%202.png)
- 프로그램은 일반적으로 함수 실행 직전에 파라미터를 스택에 역순으로 꽂아넣는다.
- cpu 상태 (7개의 파라미터를 스택에 넣고, CreateFileA API를 실행)
- CreateFileA 실행 직전(EIP가 401073 가리킴) 스택 내용. NULL ~ Keyfile.dat 순으로 들어감
- 70자(0x46)를 402173에서 읽는 ReadFile. 이 70자 데이터는 40211a로 복사된다.
![](https://raw.githubusercontent.com/seleuchel/blog/559eab4ba7b9f45e34dbbb087e9511bc5bad87a2/Mal/LENA/1/Untitled%206.png)
그냥 이대로 진행하면, 또 실패가 뜬다.
→ 또, JMP를 통해 실패문을 건너뛴다. ZF를 바꾼다.
![](https://raw.githubusercontent.com/seleuchel/blog/559eab4ba7b9f45e34dbbb087e9511bc5bad87a2/Mal/LENA/1/Untitled%207.png)
위에서 JMP하면 성공 메시지고, 아래서 JMP하면 실패 메시지다.
그러면, 위의 JMP를 위해서, 1로 set된 zf를 변경한다.
- 문자열 찾기
- 마우스 우측 → search for → all referenced text strings
![](https://raw.githubusercontent.com/seleuchel/blog/559eab4ba7b9f45e34dbbb087e9511bc5bad87a2/Mal/LENA/1/Untitled%208.png)
여기로 가면 되는데
![](https://raw.githubusercontent.com/seleuchel/blog/559eab4ba7b9f45e34dbbb087e9511bc5bad87a2/Mal/LENA/1/Untitled%209.png)
어디서 점프하는지 직관적인 선은 보이지 않지만,
아래 Pane window에서 확인 가능하다.
![](https://raw.githubusercontent.com/seleuchel/blog/559eab4ba7b9f45e34dbbb087e9511bc5bad87a2/Mal/LENA/1/Untitled%2010.png)
여기서 점프함!
그러면, 저 점프 부분으로 가기위해서 sf를 변경하도록 한다.
![](https://raw.githubusercontent.com/seleuchel/blog/559eab4ba7b9f45e34dbbb087e9511bc5bad87a2/Mal/LENA/1/Untitled%2011.png)
연속으로 존재하는 점프 3개를 잘 거치면, (앞에 sf 변경, 맨 뒤에 sf 변경)
우리가 원하는 JMP로 이동가능!
![](https://raw.githubusercontent.com/seleuchel/blog/559eab4ba7b9f45e34dbbb087e9511bc5bad87a2/Mal/LENA/1/Untitled%2012.png)
단순히 레지의 FLAG를 변경하지 않고, 어셈 명령을 바꿀 수도 있다.
이것을 패치라고 하며, 단순히 레지의 FLAG 변경하는 것은 해당 프로그램을 실행하는 다른 프로그램에 비해 코드에 손실을 가져올 수 있다.
![](https://raw.githubusercontent.com/seleuchel/blog/559eab4ba7b9f45e34dbbb087e9511bc5bad87a2/Mal/LENA/1/Untitled%2013.png)
![](https://raw.githubusercontent.com/seleuchel/blog/559eab4ba7b9f45e34dbbb087e9511bc5bad87a2/Mal/LENA/1/Untitled%2014.png)
이렇게 코드 패치내역을 볼 수 있다.
모든 수정 저장하기 (패치)
![](https://raw.githubusercontent.com/seleuchel/blog/559eab4ba7b9f45e34dbbb087e9511bc5bad87a2/Mal/LENA/1/Untitled%2015.png)
![](https://raw.githubusercontent.com/seleuchel/blog/559eab4ba7b9f45e34dbbb087e9511bc5bad87a2/Mal/LENA/1/Untitled%2016.png)
![](https://raw.githubusercontent.com/seleuchel/blog/559eab4ba7b9f45e34dbbb087e9511bc5bad87a2/Mal/LENA/1/Untitled%2017.png)
잘 동작한다.
API
- CreateFile : object를 만들거나 연다. 그리고, object에 접근할 수 있는 handle을 반환.
'MalwareAnalysis > Lena' 카테고리의 다른 글
Lena 2. reverseme 키파일링 + 어셈블 (0) | 2022.05.04 |
---|
Uploaded by Notion2Tistory v1.1.0