반응형

AOB Injection 템플릿으로 치트 엔진 오토 어셈블러의 기본을 알아보자.

 

치트 엔진 튜토리얼 2단계에서 실행한 메모리 뷰어창이다. 만약 여기에 코드를 인젝션하기 위해 오토 어셈블에서 AOB Injection을 실행하면 아래와 같은 템플릿이 기본으로 생성된다.

 

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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
{ Game   : Tutorial-i386.exe
  Version: 
  Date   : 2023-01-02
  Author : sean
 
  This script does blah blah blah
}
 
[ENABLE]
 
aobscanmodule(INJECT,Tutorial-i386.exe,29 83 B0 04 00 00) // should be unique
alloc(newmem,$1000)
 
label(code)
label(return)
 
newmem:
 
code:
  sub [ebx+000004B0],eax
  jmp return
 
INJECT:
  jmp newmem
  nop
return:
registersymbol(INJECT)
 
[DISABLE]
 
INJECT:
  db 29 83 B0 04 00 00
 
unregistersymbol(INJECT)
dealloc(newmem)
 
{
// ORIGINAL CODE - INJECTION POINT: Tutorial-i386.exe+25AEF
 
Tutorial-i386.exe+25AC9: 8D 55 DC           - lea edx,[ebp-24]
Tutorial-i386.exe+25ACC: 8D 4D F4           - lea ecx,[ebp-0C]
Tutorial-i386.exe+25ACF: E8 0C 7D FE FF     - call Tutorial-i386.exe+D7E0
Tutorial-i386.exe+25AD4: E8 B7 E3 FD FF     - call Tutorial-i386.exe+3E90
Tutorial-i386.exe+25AD9: 50                 - push eax
Tutorial-i386.exe+25ADA: 85 C0              - test eax,eax
Tutorial-i386.exe+25ADC: 0F 85 CE 00 00 00  - jne Tutorial-i386.exe+25BB0
Tutorial-i386.exe+25AE2: B8 05 00 00 00     - mov eax,00000005
Tutorial-i386.exe+25AE7: E8 44 93 FE FF     - call Tutorial-i386.exe+EE30
Tutorial-i386.exe+25AEC: 83 C0 01           - add eax,01
// ---------- INJECTING HERE ----------
Tutorial-i386.exe+25AEF: 29 83 B0 04 00 00  - sub [ebx+000004B0],eax
// ---------- DONE INJECTING  ----------
Tutorial-i386.exe+25AF5: 8D 45 D4           - lea eax,[ebp-2C]
Tutorial-i386.exe+25AF8: E8 D3 DE FD FF     - call Tutorial-i386.exe+39D0
Tutorial-i386.exe+25AFD: 8B 83 B0 04 00 00  - mov eax,[ebx+000004B0]
Tutorial-i386.exe+25B03: 68 FF 00 00 00     - push 000000FF
Tutorial-i386.exe+25B08: 8D 8D D4 FE FF FF  - lea ecx,[ebp-0000012C]
Tutorial-i386.exe+25B0E: BA FF FF FF FF     - mov edx,FFFFFFFF
Tutorial-i386.exe+25B13: E8 E8 F1 FD FF     - call Tutorial-i386.exe+4D00
Tutorial-i386.exe+25B18: 8D 4D D4           - lea ecx,[ebp-2C]
Tutorial-i386.exe+25B1B: 66 31 D2           - xor dx,dx
Tutorial-i386.exe+25B1E: 8D 85 D4 FE FF FF  - lea eax,[ebp-0000012C]
}
 

 

{}와 //의 내용은 주석이므로 설명하지 않는다.

 

1
2
3
4
5
//// -------- Main Section --------
[ENABLE]
//// -------- Enable Section --------
[DISABLE]
//// -------- Disable Section --------
 

 

전체 내용은 위와 같이 [ENABLE]과 [DISABLE]을 기준으로 Main, Enable, Disable 섹션으로 나눌 수 있다. Main 섹션은 항상 실행된다. Enable 섹션은 스크립트를 실행하면(Cheat Table Address List에서 Active 체크 박스를 클릭해서 선택하면) 실행된다. Disable 섹션은 스크립트를 정지하면(Active 체크 박스 선택 해제하면) 실행된다.

 

1
2
3
4
5
6
7
8
9
10
11
aobscanmodule(INJECT,Tutorial-i386.exe,29 83 B0 04 00 00)
 
alloc(newmem,$1000)
 
dealloc(newmem)
 
registersymbol(INJECT)
 
unregistersymbol(INJECT)
 
label(code)
 

 

템플릿에 사용된 명령어들을 하나씩 살펴보자.

 

 

aobscanmodule(INJECT,Tutorial-i386.exe,29 83 B0 04 00 00)

aobScanModule(SymbolName, ModuleName, AOBString)
- Scans the memory used by the module ModuleName for a specific byte pattern defined by AOBString and sets the resulting address to the symbol SymbolName.

지정된 모듈(Tutorial-i386.exe)에서 특정 바이트 패턴(29 83 B0 04 00 00)이 있는 메모리 영역을 찾는다. 만약 찾으면 그 주소를 심볼(INJECT)로 세팅한다. 3개의 캐릭터를 와일드카드로 사용할 수 있다.  'x', '?', '*'

예)
5x 48 8D 6x 24 E0
5? 48 8D 6? 24 E0
5* 48 8D 6* 24 E0
xx 48 8D xx 24 E0
?? 48 8D ?? 24 E0
** 48 8D ** 24 E0
x 48 8D x 24 E0
? 48 8D ? 24 E0
* 48 8D * 24 E0

 

alloc(newmem,$1000)

alloc(SymbolName, Size, AllocateNearThisAddress OPTIONAL)
- Allocates a memory block of Size bytes and defines the SymbolName in the script, pointing to the beginning of the allocated memory block.

지정한 사이즈(1000)의 메모리 블럭을 할당하고 시작 주소를 심볼(newmem)로 정의한다. ($1000은 16진수 1000을 의미한다)

 

dealloc(newmem)

dealloc(SymbolName)
- Deallocates a block of memory allocated with alloc.

alloc()으로 할당된 메모리 블럭(newmem)을 해제한다.

 

registersymbol(INJECT)

registerSymbol(SymbolName)
- Adds a symbol to the user-defined symbol list so cheat tables and the memory browser can use that name instead of an address.

심볼(INJECT)을 사용자 정의 심볼 리스트에 추가한다. 추가된 심볼은 치트 테이블과 메모리 브라우저에서 주소 대신 사용할 수 있다.

 

unregistersymbol(INJECT)

unregisterSymbol(SymbolName)
- Removes a symbol from the user-defined symbol list.

사용자 정의 심볼 리스트에서 심볼(INJECT)을 제거한다.

 

label(code)

label(LabelName)
- Enables the word 'LabelName' to be used as a symbol.

지정된 단어(code)가 심볼로 사용될 수 있게한다.

 

※ 참고 1

aobScan(SymbolName, AOBString)
- Scans all the memory for a specific byte pattern defined by AOBString and sets the resulting address to the symbol SymbolName.

메모리에서 특정 바이트 패턴(AOBString)을 찾고 그 주소를 심볼(SymbolName)로 지정한다. 3개의 캐릭터를 와일드카드로 사용할 수 있다.  'x', '?', '*'

예)
5x 48 8D 6x 24 E0
5? 48 8D 6? 24 E0
5* 48 8D 6* 24 E0
xx 48 8D xx 24 E0
?? 48 8D ?? 24 E0
** 48 8D ** 24 E0
x 48 8D x 24 E0
? 48 8D ? 24 E0
* 48 8D * 24 E0

 

assert(Address, ArrayOfBytes)
- Will check the memory address for the given bytes. If the address's memory is not what is defined by the array of bytes given, the auto assemble script will not execute.

지정된 Address에 ArrayOfBytes가 있는지 확인한다. 만약 없다면 auto assemle script는 작동하지 않는다.

ex) assert(Game.exe+123ABC, 01 02 03 0A 0B 0C)

 

globalAlloc(Symbol, Size, AllocateNearThisAddress OPTIONAL)
- Allocates a certain amount of memory and registers the specified name. Using GlobalAlloc in other scripts will then not allocate the memory again, but reuse the already existing memory. (Or allocate it anyhow if found it wasn't allocated yet) If 'AllocateNearThisAddress' is specified CE will try to allocate the memory near that address. This is useful for 64-bit targets where the jump distance could be bigger than 2GB otherwise.
지정한 사이즈의 메모리를 할당하고  할당된 메모리 주소를 이름(Symbol)으로 등록한다. 등록된 메모리 이름은 다른 스크립트나 메모리 뷰어에서 사용할 수 있다.

예)

globalAlloc(SomeSymbol, 0x4)
globalAlloc(SomeSymbol, 0x4, SomeAOBSymbol)
globalAlloc(SomeSymbol, 0x1000, Tutorial-x86_64.exe)

 

define(Name, Value)
- Creates a token with the specified name that will be replaced with the text of its value.
Note: Uses basic replacement before script is ran, whitespace is not stripped.

스크립트가 실행되기 전 교체될 텍스트 토큰을 생성한다.

 

ex 1)

아래 코드가..
define(address, 00 12 3A BC)
...
address:
  db 90 90 90

 

이렇게 바뀐다.
00 12 3A BC:
  db 90 90 90

 

ex 2)

아래 코드가..
define(fullValue,(float)100.0)
...
mov eax,fullValue

이렇게 바뀐다.
mov eax,(float)100.0

 

※ 참고 2

Auto Assembler Basics

 

템플릿 코드를 Injection한 화면이다.어셈블리 코드가 변경되었는데 왜 이렇게 된건지 살펴보자.

 

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
[ENABLE]
 
aobscanmodule(INJECT,Tutorial-i386.exe,29 83 B0 04 00 00) // should be unique
// 코드를 Enable하면 우선 Tutorial-i386.exe 모듈 메모리 영역에서 29 83 B0 04 00 00 패턴을
// 찾고 그 주소를 INJECT라는 심볼로 세팅한다.
alloc(newmem,$1000)
// 4096바이트($1000) 크기의 메모리 블럭을 할당하고 그 시작 주소를 newmem으로 정의한다.
 
label(code)
label(return)
// code와 return 이라는 심볼을 정의한다.
 
newmem:
// 위에서 할당된 newmem 영역에 삽입할 코드를 작성한다.
 
code:
  sub [ebx+000004B0],eax
  jmp return
// 원래 있던 어셈블리 코드가 그대로 따라왔다. 위 newmem 에서 작성하는 코드 뒤에 바로 붙는다.
// 마지막엔 return 주소로 점프한다.
 
 
INJECT:
  jmp newmem
  nop
// INJECT 심볼 위치에 위 코드가 overwrite된다. 원래 있던 어셈블리 명령어 sub [ebx+000004B0],eax
// 의 기계어는 29 83 B0 04 00 00 이고 jmp newmem의 기계어는 E9 0C A5 CE FF이기 때문에 1바이트가
// 부족해 nop 명령어가 추가 되었다.
 
return:
// INJECT 심볼의 내용이 모두 끝나는 위치 바로 아래(Tutorial-i386.exe+25AF5)가 return 심볼이
// 가리키는 주소가 된다.
 
registersymbol(INJECT)
// INJECT를 사용자 정의 심볼 리스트에 추가한다. 위 화면에서 보면 Tutorial-i386.exe+XXXXX 같은
// 실제 주소가 아닌 INJECT라는 문자로 표시되는걸 확인할 수 있다.
 

 

 

alloc()으로 할당된 메모리 블럭을 확인해 보면 코드가 인젝션 되어 있다.

 

 

코드 인젝션을 해제한 화면이다. 원래 상태 그대로 복구되었다. 어떻게 된건지 확인해 보자.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[DISABLE]
 
INJECT:
  db 29 83 B0 04 00 00
// INJECT 심볼 위치에 원래 있던 위 기계어를 그대로 overwrite 한다.
// 이 기계어의 의미는 sub [ebx+000004B0],eax 이다. 기계어로 overwrite하지
// 않고 어셈블리 명령어를 사용하면 컴퓨터 환경(16비트, 32비트등)에 따라 다른
// 기계어가 적용되는 경우가 발생하기도 한다.
 
unregistersymbol(INJECT)
// 사용자 정의 심볼 리스트에서 INJECT 심볼을 제거한다. 위 화면에서 주소 대신
// 쓰였던 INJECT 문자가 사라지고 원래 주소로 복구된것을 확인할 수 있다.
dealloc(newmem)
// alloc()으로 할당한 메모리 블럭을 해제한다.
 

 

 

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

도스박스에서 실행한 고전 게임을 치트해 보자. 코드 인젝션으로 번개와 폭탄을 무한대로 사용할 수 있게 한다.

 

도스박스를 실행한다.

 

Rick Dangerous 2를 실행한다.

 

Rick Dangerous II.zip
0.19MB

 

게임이 시작되면 번개를 사용한다.

 

번개 숫자가 변하면 번개가 저장된 메모리를 찾을 수 있다. (Value Type은 2Bytes로 설정해야 한다)

 

 

번개 메모리 주소에서 Find out what writes to this address를 실행한다.

 

다시 번개를 한 번 쏘면 어떤 코드가 번개 메모리 주소를 사용하는지 찾을 수 있다. Show disassembler 버튼을 클릭한다.

 

Memory Viewer에 어셈블리 코드가 표시된다.

 

Tools - Auto Assemble을 클릭한다.

 

 

Auto Assemble 창이 뜨면 Template - AOB Injection을 클릭한다.

 

번개 메모리에 6(번개 최대치)을 저장하는 코드를 newmem영역에 작성한다.

 

File - Assign to current cheat table을 클릭한다.

 

Cheat Table Address List에 스크립트가 추가되었다. Active 체크박스를 클릭해 활성화 한다.

 

 

게임에 오류가 발생한다. 왜 그럴까?

 

다시 Memory Viewer를 확인해 보자. 새로운 코드가 생성된 곳으로 점프하는 명령어가 잘 들어가 있다.

 

새로운 코드도 잘 들어가 있다. 이유를 알 수가 없다.

 

처음부터 다시 해 보자. 게임을 시작하고 번개가 저장된 메모리 주소를 찾는다.

 

 

어떤 코드가 번개가 저장된 메모리 주소를 사용하는지 찾은 후 이번엔 Find out what addresses this code accesses를 실행한다. 이 코드가 어떤 메모리 주소에 접근하는지 찾아준다. 예상대로라면 번개 메모리 주소만을 접근해야 한다.

 

게임에 오류가 발생한 이유를 찾았다. 우리가 찾은 코드는 번개 저장 메모리뿐만 아니라 다른 메모리에도 엄청나게 많은 접근을 하고 있었던 것이다. 이 모든 메모리에 6을 덮어 썼으니 오류가 나지 않을 수 없었다. 어떻게 해야 번개 메모리에만 6을 저장할 수 있을까?

 

다시 Memory Viewer로 돌아와서 메모리 덤프창에서 우클릭 - Goto address를 클릭한다.

 

번개가 저장된 메모리 주소를 입력하고 OK를 클릭한다.

 

 

번개가 저장된 메모리(04 00)가 표시된다. (그 옆의 06 00은 폭탄이 저장된 메모리이고 다시 그 옆의 06 00은 생명이 저장된 메모리이다) 주변을 살펴보자. 00, 09, FF등 별 특이한 값은 보이지 않지만 0A590B31~0A590B34에 JOHN이라는 이름이 기록되있다. 우리가 찾은 코드가 접근하는 다른 메모리 근처엔 없을거 같은 특이한 값이다. (JOHN 이외의 다른 이름들은 높은 점수를 기록한 사람들의 이름이 저장된 HALL OF FAME에 나오는 이름들이다. JOHN은.. 모르겠다)

 

이번엔 JOHN이라는 값을 이용해 번개 저장 메모리 주소를 구분하고 번개와 폭탄을 모두 6으로 덮어쓰는 코드를 작성한다. JOHN은 번개 메모리 주소에서 offset이 0x61이다. 또 번개 메모리 주소 바로 옆, offset 0x02에 폭탄 갯수가 저장되어 있다.

 

코드를 실행하면 번개를 사용할때마다 폭탄과 번개가 6으로 세팅된다.

 

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

치트 엔진으로 삽입한(inject) 코드를 enable/disable 하기 위해 Cheat Table Framework code 사용할 수 있다. 하지만 자세히 보지 않으면 원치 않는 결과를 얻게 되므로 조심해야 한다.

 

치트 엔진 튜토리얼을 실행하고 Step 7: Code Injection 까지 진행한다.

 

Health 메모리를 찾는다.

 

Health 메모리에 쓰기를 시도하는 코드를 찾는다.

 

쓰기 코드를 찾았으면 Show disassembler 버튼을 클릭한다.

 

 

Health 메모리에 저장된 값을 1 감소(sub) 시키는 코드가 선택된다.

 

Tools - Auto Assemble 을 클릭한다.

 

삽입할 코드를 enable/disable 할 수 있도록 Cheat Table framework code를 선택한다.

 

Code injection을 선택한다.

 

 

코드를 삽입하고 복구하는 기본 코드가 작성되었다. 코드를 수정하지 않았으므로 프로그램은 변경되지 않는다.

 

Assign to current cheat table을 선택한다.

 

Cheat Table Address List에 스크립트가 추가되었다.

 

Active 체크박스를 클릭해 enable 시킨다.

 

 

스크립트가 삽입된 주소로 점프하는 코드로 변경되었다.

 

다시 Active 체크박스를 클릭해 disable 시킨다.

 

변경된 점프 코드가 다시 원래 sub 코드로 복구되었다.

 

하지만 튜토리얼의 Hit me 버튼을 클릭하면 오류가 발생하고 프로그램이 종료되어 버린다.

 

 

왜 그럴까? 원래 코드와 복구된 코드를 다시 살펴보자.

위 Memory Viewer가 원래 코드고 아래 Memory Viewer가 복구된 코드다.

원래 코드나 복구된 코드나 ebx 레지스터에 저장된 메모리 주소에서 4A4 바이트 떨어진 곳에 저장된 값에서 1을 빼는 내용으로 동일하지만 자세히 보면 Opcode가 다른것을 확인할 수 있다. 원래 코드의 Opcode는 83이고 복구된 코드의 Opcode는 81이다. 두 번째 operand도 값은 1로 동일하지만 크기가 1바이트(01)와 4바이트(00000001)로 큰 차이가 발생했다. 이렇게 코드가 바뀌었지만 내용은 같기때문에 별 문제가 없을것 같지만 명령어 크기가 바뀌는 바람에 그 다음 명령어 영역까지 침범한 것은 큰 문제이다. (그래서 프로그램이 오류로 종료되어 버리는 것이다)

 

스크립트의 복구 내용을 살펴보면 원래 어셈블리어 코드 그대로 사용했음을 확인할 수 있다. 그런데 그 어셈블리어 코드가 원래 옵코드와 오퍼랜드로 복구되지 않는것이 문제이다.

 

인텔 소프트웨어 개발자 메뉴얼을 확인해 보자.

 

intel Software Developer’s Manual_Vol_2.pdf
11.06MB

 

sub 명령어는 여러가지 Opcode가 존재한다.

원래 코드의 83은 imm8(8비트 값)을 오퍼랜드로 사용하지만 복구된 코드의 81은 imm32(32비트 값)을 오퍼랜드로 사용한다. 복구할 스크립트의 sub 명령어를 기계어로 번역할때 Opcode를 81로 사용하기 때문에 sub dword ptr [ebx+000004A4], 01 이라는 어셈블리 명령어의 두 번째 오퍼랜드 01을 0x01로 1바이트 값이 아닌 0x00000001로 4바이트 값으로 번역하는 것이다. 치트엔진은 튜토리얼이 32비트 프로그램이므로 당연히 4바이트 값을 사용했을것이라 생각하는것 같다. 어쨌든 원래 코드로 복구시키지 못하므로 버그라고 봐야 할거같다.

 

 

해결 방법은 간단하다.

위 그림처럼 sub dword ptr [ebx+000004a4], 01 코드를 주석처리하고 그 아래 db 83 AB A4 04 00 00 01을 주석 해제한다. 어셈블리어로 작성한 코드를 기계어로 번역하지 않고 원래 있던 기계어를 다시 그대로 바이트 단위로 정의(db: define byte)하는 것이다.

 

아니면 위 그림처럼 dword(4바이트)를 byte(1바이트)로 바꿔도 된다.

 

r/m8, imm8 오퍼랜드를 사용하는 80 옵코드로 복구되지만 기계어로 번역된 결과의 길이가 같아 다른 명령어를 침범하지 않고 실행에도 문제가 없다.

 

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

Cheat Engine(CE)으로 포인터의 포인터를 찾아 보자.

 

CE을 실행하고 Help - Cheat Engine Tutorial 을 실행 한다.

 

Cheat Engine에서 Tutorial을 열어 준다.

 

Edit - Settings를 클릭하고 Cheat Engine settings 창이 열리면 Pointer adding: Append pointerline instead of insert를 체크 한다.

 

Tutorial에서 찾아야 하는 값인 3045를 First Scan 으로 찾아서 Address List에 추가 한다.

 

 

Address List에 추가된 주소는 첫 번째 포인터가 가리키는 주소와 그 주소에 저장된 값이다. 4 단계에 걸친 포인터를 모두 찾아 주어야 한다. 추가된 목록에서 우클릭 - Find out what accesses this address(F5)를 클릭 한다.

 

열려 있는 프로세스에 Cheat Engine의 debugger를 attach 한다는 메세지 박스가 나온다.

 

Yes 를 클릭하면 아래와 같은 창이 뜬다.

 

Tutorial 로 돌아와 Change value 버튼을 클릭 한다.

 

 

 

Find out what accesses this address 로 지정한 주소에 접근하는 opcode가 표시 된다.

 

More information 버튼을 클릭하면 추가 정보가 표시 된다. 내용을 확인해 보면 eax에 저장된 값을 rsi+18에 복사하고 있다.

rsi의 주소는 01587460이고 여기에 offset 값 18을 더하면 01587478로 위에서 CE으로 찾은 주소의 값과 일치 한다.

 

CE에서 Hex 체크 박스를 클릭하고 rsi 주소값을 입력한 다음 New Scan을 클릭하고 First Scan 한다. 아래와 같이 rsi 주소 값을 가지는 메모리의 주소(첫 번째 포인터)를 찾았다. 이 상태에서 Add Address Manually 버튼을 클릭 한다.

 

Add address 창이 뜨면 Pointer 체크 박스를 클릭 하고 위에서 찾은 메모리 주소를 입력한다. offset 값으로 18을 입력 하면 최종 값인 3559가 표시 된다.

 

 

OK를 클릭하면 CE에 아래와 같이 표시 된다.

 

이제 이 포인터의 포인터를 찾아 보자. 추가한 포인터에서 F5를 눌러 Find out what accesses this address를 실행하면 아래와 같은 메세지가 나온다.

Find out what accesses this pointer를 클릭한다.

 

Tutorial로 돌아가 Change value 버튼을 클릭하면 아래와 같이 포인터에 접근하는 opcode 목록을 표시해 준다. 첫 번째 opcode의 operand 인 rsi 값을 확인해 보면 07312500으로 위에서 찾은 포인터의 주소와 일치 한다.

 

rsi 값을 가지는 주소(포인터)를 찾아 보자. 015661E8에 같은 값이 저장되어 있는걸 확인 할 수 있다.

 

 

리스트에 추가된 포인터를 더블 클릭하고 Add Offset 버튼을 클릭하면 아래와 같은 화면으로 바뀐다.

 

하단 주소 입력 에디트 박스에 포인터 주소값을 입력해 주면 아래와 같이 표시된다. OK 버튼을 클릭한다.

 

별 다른 변화는 없어 보이지만 포인터의 포인터까지 찾아 놓은 상태이다.

 

다시 그 포인터의 포인터를 찾는 과정을 반복하면 아래와 같이 더 이상 포인터로 지시되지 않는 녹색 주소값이 나온다. (CE 에서는 static address가 녹색으로 표시 된다)

 

 

이 마지막 포인터를 추가해 준다.

 

마지막 포인터까지 추가되었으면 Active 체크 박스를 클릭해서 값을 고정 시키고 Value를 5000으로 수정 한다.

 

 

Tutorial로 돌아가 Change pointer버튼을 클릭하면 3초 후 Next 버튼이 활성화 된다. a pointer to a pointer to a pointer to a pointer to the health 값을 찾은 것이다.

 

 

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

x64dbg에서 패치한 파일은 아래와 같이 ollydbg와는 다른 방식으로 저장한다.

 

필요한 부분을 패치 한다. 아래 예에서는 4바이트를 패치 했다.

 

File - Patch file... 을 클릭 한다.

 

패치된 4바이트가 표시 된다. Patch File 버튼을 클릭 한다.

 

원하는 이름을 입력하고 저장 버튼을 클릭 한다.

 

 

패치가 적용되었다는 메세지 박스가 나타난다.

 

지정된 폴더에 패치된 파일이 생성되어 있다.

 

 

 

 

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

x64dbg를 설치하고 실행해 보면 아래와 같이 밝은 배경으로 표시 된다.

 

아래 링크에서 원하는 Color Scheme을 다운 받고 압축을 풀어 주자. (

mostlyblack.ini
다운로드

)

x64dbg Color Schemes

 

Options - Import settings... 를 선택 한다.

 

다운 받은 Color Scheme 파일을 선택해 준다.

 

선택한 Color Scheme이 바로 적용 된다.

 

 

파일을 열어 보면 아래와 같이 표시 된다.

 

 

 

반응형

'Reverse Engineering' 카테고리의 다른 글

Cheat Engine으로 Multilevel pointers 찾기  (0) 2019.03.20
x64dbg 패치한 파일 저장하기  (0) 2019.03.05
Cheat Engine으로 Pointer 찾기  (2) 2019.02.13
Back to user mode  (4) 2019.02.10
Windows 10에서 *.hlp 파일 열기  (10) 2019.02.05
Posted by J-sean
:
반응형

※ 참고: 포인터 스캐너 사용법

 

Cheat Engine으로 간단하게 Pointer를 찾을 수 있다.

 

Cheat Engine에서 Tutorial 프로세스를 열어 준다. Value를 변경해 가며 정확한 Address를 찾는다.

 

찾은 Address에서 오른쪽 클릭 하고 'Find out what accesses this address'를 클릭한다.

 

Cheat Engine에 debugger를 붙여 준다.

 

 

아래와 같은 창이 뜬다.

 

Tutorial로 돌아가 Change value 버튼을 클릭해 값을 변경 하면 018F3D30 주소에 접근한 opcode들이 표시 된다. 그 중 두 번째 opcode가 018F3D30 위치의 값을 바꾼다는 것을 알 수 있다. (아래 창에서 << 표시된 opcode) More information을 클릭하면 약간의 추가 정보가 표시 된다.

 

Cheat Engine에서 value가 저장된 Address인 018F3D30을 다시 Hex scan 한다.

 

018F3D30이 저장된 Address가 Pointer의 Address 이다. Add Address Manually 버튼을 클릭한다.

 

 

Pointer를 체크한다.

 

Pointer의 Address를 입력한다. offset 값은 없으므로 0으로 둔다.

 

Value가 저장된 위치를 가리키는 Pointer가 추가 된다.

 

Value를 5000으로 수정하고 Active를 체크한다. (Value가 5000으로 고정 된다)

 

 

Tutorial에서 Change value 버튼을 클릭하면 Value가 바뀌지만 메모리 상에서는 다시 5000으로 돌아간다. Change pointer 버튼을 클릭하면 Pointer가 가리키는 주소(Value 값이 저장된 주소)가 바뀌고 Cheat Engine 에서 찾아 놓은 Pointer 가 가리키는 주소값도 똑같이 바뀐다. Next 버튼이 활성화 되고 Pointer를 찾았음을 확인 할 수 있다.

 

 

이번에는 아래와 같은 코드로 프로그램을 만들어서 정확히 확인해 보자. 

 

Pointer.exe
다운로드

 

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
43
#include <iostream>
 
using std::cout;
using std::cin;
using std::endl;
 
int main()
{
    int* p = new int;
    *= 100;
    int choice;
 
    cout << "Value(*p): " << *<< endl;
    cout << "Pointer value(p): " << p << endl << endl;
    cout << "1: Change value\n2: Change pointer value\nChoose: ";
 
    while (cin >> choice)
    {
        switch (choice)
        {
        case 1:
            (*p)++;
            cout << endl << "Value(*p): " << *<< endl;
            cout << "Pointer value(p): " << p << endl << endl;
            break;
        case 2:
            p = new int;
            *= 100;
            cout << endl << "Value(*p): " << *<< endl;
            cout << "Pointer value(p): " << p << endl << endl;
            break;
 
        default:
            break;
        }
 
        cout << "1: Change value\n2: Change pointer value\nChoose: ";
    }
 
    delete p;
 
    return 0;
}
cs

 

프로그램을 실행 시키면 포인터에 저장된 주소(p)와 그 주소에 저장된 값(*p)이 표시 된다.

아래와 같이 1을 선택하면 값을 1 증가 시키고 2를 선택하면 포인터에 저장된 주소를 다시 할당 한다.

 

프로그램을 다시 실행하고 Cheat Engine으로 Value를 변경해 가며 주소를 찾는다.

 

 

 

프로그램에서 주소값을 표시해 주므로 Cheat Engine에서 찾은 주소가 맞는지 쉽게 확인 된다.

마찬가지로 Find out what accesses this address 로 어떤 코드가 이 주소에 접근하는지 확인해 보자.

 

 

More informatioin의 내용도 확인해 보자.

 

Value의 주소값을 Hex Scan으로 검색한다. 아래와 같이 두 개의 주소가 확인 되었다.

 

 

프로그램에서 2번을 선택해 Pointer가 가리키는 주소를 변경해 보자.

 

00F3F764에 저장된 값이 프로그램과 동일하게 변경되는걸 확인 할 수 있다. 00F3F764가 포인터의 주소이다.

 

Add Address Manually로 Pointer를 추가해 준다.

 

 

 

프로그램에서 Value와 Pointer value를 변경하면 Cheat Engine에 찾아 놓은 포인터에도 똑같이 적용되는걸 확인 할 수 있다.

 

 

 

반응형

'Reverse Engineering' 카테고리의 다른 글

x64dbg 패치한 파일 저장하기  (0) 2019.03.05
x64dbg Color Scheme 바꾸기  (0) 2019.02.19
Back to user mode  (4) 2019.02.10
Windows 10에서 *.hlp 파일 열기  (10) 2019.02.05
IDA Pro Skin 바꾸기  (1) 2019.02.04
Posted by J-sean
:

Back to user mode

Reverse Engineering 2019. 2. 10. 22:21 |
반응형

프로세서가 kernel mode에서 user mode로 변경되는 시점을 간단히 찾을 수 있다. (User mode and kernel mode)

 

 

 

예를 들어 Message box가 종료되는 지점을 찾아 보자. ollydbg에서 분석할 프로그램을 열어 준다.

 

RegisterMe.zip
0.00MB

(password: lena)

 

 

F9를 눌러 실행 한다.

 

아래와 같은 Message box가 나타난다.

 

F12를 눌러 정시 시킨다.

 

 

아래와 같은 곳으로 이동 된다.

 

Alt + F9를 눌러 back to user mode를 실행 한다.

 

오른쪽 아래에 Till user가 표시 된다.

 

'Register Me' 메세지 박스에서 '확인'을 클릭하면 아래와 같이 MessageBoxA CALL 이 종료되는 시점에서 정지 된다.

 

 

이번엔 scanf 가 종료되는 지점을 찾아 보자. 아래와 같은 소스로 실행 파일을 만들어 준다. (

FindMe.zip
다운로드

)

1
2
3
4
5
6
7
8
9
10
11
12
#include <stdio.h>
 
int main()
{
    int i;
 
    printf("Enter a number: ");
    scanf_s("%d"&i);
    printf("Number: %d", i);
 
    return 0;
}
cs

 

ollydbg(v.2.01)로 열어 준다.

 

F9를 눌러 실행 한다.

 

아래와 같이 숫자를 입력하는 콘솔창이 뜬다.

 

 

다시 ollydbg로 돌아와 F12를 눌러 정지 시킨다. 하지만 여기서는 Paused 상태가 되지 않고 Pausing 상태가 된다.

 

콘솔창에서 숫자를 입력 한다.

 

숫자를 입력하면 아래와 같은 주소로 이동하고 정지 상태가 된다.

 

F8, Alt + F9, Ctrl + F9 를 적당히 눌러가며 진행 하면 scanf가 종료되는 것으로 보이는 위치가 나타난다.

 

 

같은 파일을 x32dbg로 열어 보자.

 

F9를 눌러 진행 한다.

 

한번 더 F9를 눌러 진행하면 아래와 같이 Running 상태가 된다.

 

숫자를 입력하라는 콘솔창이 뜬다.

 

 

x32dbg로 돌아가 Threads 창을 열어 준다.

 

Title Bar에는 Main Thread가 선택되어 있는 것 처럼 표시 되지만 Main Thread가 아닌 2번 thread가 활성화 되어 있다. 이 상태에서는 break point가 제대로 작동하지 않는다. Main Thread를 활성화 해 준다.

 

아래와 같은 주소로 이동 된다. F12를 눌러 Pause 한 후(F12를 한 번 누르면 화면에는 아무것 도 표시되지 않는다. 두 번 누르면 Error setting breakpoint at XXXXXXXX! (SetBPX) 가 표시 되지만 무시하자) 콘솔창에서 숫자를 입력한다.

 

숫자를 입력하고 나면 아래와 같이 Paused 상태가 된다.

 

 

F8, Alt + F9, Ctrl + F9 를 적당히 눌러가며 진행 하면 scanf가 종료되는 것으로 보이는 위치가 나타난다.

 

스크롤을 조금 올려 보면 프로그램의 전체적인 내용을 파악 할 수 있다. pdb파일이 같이 있기 때문에 소스 라인까지 표시 된다.

 

 

반응형

'Reverse Engineering' 카테고리의 다른 글

x64dbg Color Scheme 바꾸기  (0) 2019.02.19
Cheat Engine으로 Pointer 찾기  (2) 2019.02.13
Windows 10에서 *.hlp 파일 열기  (10) 2019.02.05
IDA Pro Skin 바꾸기  (1) 2019.02.04
ollydbg Jump 위치 표시  (2) 2019.02.02
Posted by J-sean
: