2011-02-15 4 views
3

나는 게임에 C++ DLL을 주입하고 있으며, 필자의 일부 코드에 함수를 연결하고 싶습니다. DLL은 매번 다른 위치에 매핑되기 때문에 직접 점프와 호출이 더 쉬울 것입니다. 또한 이것은 후크이기 때문에 함수로 돌아갈 때 스택이나 레지스터를 변경하고 싶지 않습니다.관련성 (x86)을 사용하지 않고 ASM에서 직접 호출/점프

포인터를 가질 수 있도록 Asm을 저장하는 char *을 선언합니다. (char * asm = "\ x00";) 16 진수를 제공 할 수 있으면 시간이 절약됩니다.

필자는 FF와 EA를 사용하여 전화와 점프를 시도했지만 어떻게 작동하는지 이해하지 못한다고 생각합니다. 내가 그 (것)들을 사용할 때 나는 지금 수술 중에 결장이 있음을 알아 차렸다.

JMP FAR FWORD PTR DS:[00000000] 

점프 위치에 대한 포인터를 사용한 후에도 작동하지 않았지만 작동하지 않았습니다.

는 여기에 내가 다른 방법을 시도 시작하기 전에 사용 된 어셈블리의 :
01270000 50    PUSH EAX 
01270001 57    PUSH EDI 
01270002 E8 E9CC1BFF  CALL fwound.0042CCF0 
01270007 5F    POP EDI 
01270008 58    POP EAX 
01270009 50    PUSH EAX      //replacements 
0127000A 8D4C24 7C  LEA ECX,DWORD PTR SS:[ESP+7C] // 
0127000E - E9 36D11BFF  JMP fwound.0042D149 

내가 따라서이 시간에 필요한 관련 점프/호출을 알고, 올리을 사용하여 해당 블록을했다.

Asm이 메모리에있는 상태에서 함수의 두 작업 (이 작업은 대체 됨)을 작성해야이 위치로 이동할 수 있습니다.

그렇다면 직접 점프 및 전화를 사용하도록 Asm 블록을 수정하려면 어떻게해야합니까? 나는 사물의 종류를 해본 적이

답변

4

당신이처럼 코딩 할 수 있습니다 (GCC 스타일/AT & T 어셈블리 구문) :

이 (32 비트 x86에서) 열 바이트로 조립
jmp *.Ltgtaddr 
.Ltgtaddr: .long absoluteAddrOfFunctionToCall 

- 32 비트 메모리 피연산자 절대 JMP에 대한 ff 25, 그 다음에 다음 단어의 주소가있는 4 바이트와 코드의 (절대) 대상 주소 인 내용이옵니다.

편집 : 아래 섹션을 컴파일되고 테스트 된 예제로 업데이트했습니다.

C 소스 코드에서 이와 같은 트램펄린을 동적으로 생성 할 수 있습니다. 예제 소스 (64 비트에 트램 폴린을 변환하는 방법을 독자에게 연습 문제로 남겨 32 비트 86가 필요) : 나를 위해

#include <sys/mman.h> 
#include <stdio.h> 

void oneWay(char *str, int arg) 
{ printf("string is \"%s\", int is %d\n", str, arg); } 

void otherWay(char *str, int arg) 
{ printf(str, arg); printf("\n"); } 

void *trampGen(void *tgtAddr) 
{ 
    char *trampoline = mmap(NULL, 10, PROT_EXEC | PROT_WRITE | PROT_READ, 
     MAP_PRIVATE | MAP_ANON, -1, 0); 
    trampoline[0] = (char)0xff; trampoline[1] = (char)0x25; 
    *(char**)(trampoline+2) = trampoline + 6; 
    *(void**)(trampoline+6) = tgtAddr; 
    return trampoline; 
} 

int main(int argc, char **argv) 
{ 
    void * (*funcptr)(char*, int) = trampGen(oneWay); 
    *funcptr("Test %d String", 12345); 
    *(void **)(((char *)funcptr) + 6) = otherWay; 
    *funcptr("Test %d String", 12345); 
    munmap(funcptr, 10); 
    return 0; 
} 

출력 : 그것은 약간 비효율적

$ ./tt 
string is "Test %d String", int is 12345 
Test 12345 String 

주 전체 따로 설정 MMU 페이지는 10 바이트 만 사용합니다. trampolines에 대한 자신의 메모리 관리자를 구현하십시오. 둘 중 하나 이상이 필요하면 ...

0

,
하지만 난 당신이 너무마다이 (고정)을 오프셋 추가 (올리 디버그로 찾아)이 게임의 알려진 메모리 위치로부터의 오프셋 (offset)를 사용한다고 생각합니다 (가변) 주소. 예를 들어,이 주소는 ss:ebp에있는 반송 주소 일 수 있으며 그 오프셋은 ollyDBG의 도움으로 계산됩니다.