2014-07-10 3 views
1

함수 메모리 (void)를 바이트 배열 (unsinged char[])에 덤프하고 싶습니다. Aftwerwards에서 더미 함수는 바이트 배열을 가리키고 더미 함수가 실행되어야한다.함수의 메모리 덤프

내가 덤프하려는 기능 :

void CallMessageBoxExA() 
{ 
    message = "ManualMessageBoxExA"; 
    caption = "Caption"; 
    pAddr = GetProcAddress(GetModuleHandle(L"User32.dll"), "MessageBoxExA"); 

    __asm // Call MessageBoxA 
    { 
     push dword ptr 0 //--- push languageID: 0 
     push dword ptr 0 //--- push style: 0 
     push dword ptr caption //--- push DWORD parameter (caption) 
     push dword ptr message //--- push DWORD parameter (message) 
     push dword ptr 0 //--- push hOwner: 0 
     mov eax, pAddr 
     call eax //-- call address of the function, which is currently in EAX 
    } 
} 

를 메모리 덤프 :

string DumpMemory(void *pAddress, int maxLength) 
{ 
    string result = ""; 
    const unsigned char * p = reinterpret_cast< const unsigned char *>(pAddress); 
    cout << "Memory location: 0x" << hex << (unsigned int)p << endl; 
    for (unsigned int i = 0; i < maxLength; i++) { 
     string code = ""; 
     stringstream ss; 
     ss << hex << int(p[i]); 
     ss >> code; 
     result += code; 
    } 
    return result; 
} 

DumpMemory 인쇄 콘솔에 메모리 위치보고, 올리 디버그는이 위치에서 JMP 명령을 보여줍니다

CPU Disasm 
Address Hex dump   Command         Comments 
00281627 $-/E9 044C0000 JMP CallMessageBoxExA 

올바른 메모리 위치, 또는 JMP를 따라야합니까?

CPU Disasm 
Address Hex dump   Command         Comments 
00286230 /$ 55   PUSH EBP         ; ASM.CallMessageBoxExA(void) 
00286231 |. 8BEC   MOV EBP,ESP 
00286233 |. 81EC C0000000 SUB ESP,0C0 
00286239 |. 53   PUSH EBX 
0028623A |. 56   PUSH ESI 
0028623B |. 57   PUSH EDI 
0028623C |. 8DBD 40FFFFFF LEA EDI,[EBP-0C0] 
00286242 |. B9 30000000 MOV ECX,30 
00286247 |. B8 CCCCCCCC MOV EAX,CCCCCCCC 
0028624C |. F3:AB   REP STOS DWORD PTR ES:[EDI] 
0028624E |. C705 A8562900 MOV DWORD PTR DS:[message],OFFSET 00291D ; ASCII "ManualMessageBoxExA" 
00286258 |. C705 AC562900 MOV DWORD PTR DS:[caption],OFFSET 00291D ; ASCII "Caption" 
00286262 |. 8BF4   MOV ESI,ESP 
00286264 |. 68 041E2900 PUSH OFFSET 00291E04      ; ASCII "MessageBoxExA" 
00286269 |. 8BFC   MOV EDI,ESP 
0028626B |. 68 D01D2900 PUSH OFFSET 00291DD0      ; /ModuleName = "User32.dll" 
00286270 |. FF15 00602900 CALL DWORD PTR DS:[<&KERNEL32.GetModuleH ; \KERNEL32.GetModuleHandleW 
00286276 |. 3BFC   CMP EDI,ESP 
00286278 |. E8 5BB2FFFF CALL 002814D8       ; [_RTC_CheckEsp 
0028627D |. 50   PUSH EAX         ; |hModule 
0028627E |. FF15 04602900 CALL DWORD PTR DS:[<&KERNEL32.GetProcAdd ; \KERNEL32.GetProcAddress 
00286284 |. 3BF4   CMP ESI,ESP 
00286286 |. E8 4DB2FFFF CALL 002814D8       ; [_RTC_CheckEsp 
0028628B |. A3 B0562900 MOV DWORD PTR DS:[pAddr],EAX 
00286290 |. 6A 00   PUSH 0 
00286292 |. 6A 00   PUSH 0 
00286294 |. FF35 AC562900 PUSH DWORD PTR DS:[caption] 
0028629A |. FF35 A8562900 PUSH DWORD PTR DS:[message] 
002862A0 |. 6A 00   PUSH 0 
002862A2 |. A1 B0562900 MOV EAX,DWORD PTR DS:[pAddr] 
002862A7 |. FFD0   CALL EAX 
002862A9 |. 5F   POP EDI 
002862AA |. 5E   POP ESI 
002862AB |. 5B   POP EBX 
002862AC |. 81C4 C0000000 ADD ESP,0C0 
002862B2 |. 3BEC   CMP EBP,ESP 
002862B4 |. E8 1FB2FFFF CALL 002814D8       ; [_RTC_CheckEsp 
002862B9 |. 8BE5   MOV ESP,EBP 
002862BB |. 5D   POP EBP 
002862BC \. C3   RETN 

가 바이트 배열에서 더미 기능을 포인팅 :

void(*func_ptr)(); 
func_ptr = (void(*)()) &foo[0]; // make function point to foo[] 
(*func_ptr)(); // Call the function 

이 바이트 배열에 더미 기능 점수를 만들 수있는 올바른 방법인가에

메모리 위치 점프 리드?

언제 기능 종료에 도달 했습니까? 나는 단순히 다른 반환 연산 코드 (C3 -> 호출자 근처에서 반환, CB -> 호출자에서 멀리 반환 ...)를 확인해야합니까?

추신 : C++을 처음 접했을 때 단순한 (예 : 그다지 정교하지 않은) 해결책이 선호됩니다.

편집 : Windows 환경에서 이것을 수행하고 싶습니다.

+3

[휴대용 방식으로는 불가능합니다.] (http://en.wikipedia.org/wiki/Harvard_architecture) 플랫폼 별 조언 (Windows처럼 보임)을 원하면 플랫폼을 지정하십시오. –

+3

나는 훨씬 덜 복잡한 것으로 C++ 기술을 개발할 것을 권장합니다. –

+0

당신이 찾고있는 것은 세계에서 소수의 개발자들이 사용하는 * VERY * 강력한 기능입니다 (주로 JIT 런타임 언어 작성). 참고로, 내 자신의 서클에서 10 년의 C++ 개발자로서, 나는 개인적으로 누가 그것을 시도했는지 아는 유일한 사람입니다. –

답변

1

VirtualAllocEx을 사용하여 할당 된 메모리 블록에 "copied"기능을 저장해야합니다. 최신 OS에서는 각 페이지에 내용이 실행 가능 여부를 선언하는 비트가 있습니다. 이것은 버퍼 오버런의 피해를 최소화하는 데 사용됩니다. 기본적으로 메모리는 실행 가능하지 않습니다. PAGE_EXECUTE_READWRITE 보호 모드와 함께 VirtualAllocEx을 사용하면 메모리 블록에 쓸 수 있고 그 블록에서 실행할 수 있습니다.

"언제 기능의 끝나기"라는 질문에 대해서는 실제로 대답 할 수 없습니다. 찾을 수있는 일반적인 패턴이 있지만 x86에는 함수의 "끝"을 식별 할 수있는 방법이 없습니다.

+0

또한 데이터를 실행하려고 할 때 데이터 정렬을 확인하십시오. x86에 opcode에 대한 정렬 요구 사항이있는 경우에는 필자는 그 사실을 기억하지 못하지만, 그렇게 할 경우, 해당 요구 사항을 고려해야합니다. –

+0

그리고 나서 코드 모션 때문에 픽스 업을 적용해야합니다. 그리고 점프 테이블을 감지하고 수정하십시오. 이것은 신속하게 중지 문제로 바뀝니다. –

0

점프를 따라해야 할 것 같습니다. 점프를하면 코드가 위에서 컴파일 한 코드와 일치합니다.

또한 DumpMemory가 pAddressIn의 주소를 사용하고 있습니다. 함수에 pAddress라는 변수가 전달됩니다. 이것은 오타이거나 다른 곳에서 선언 된 변수를 참조하는 것입니다. 나는 당신이 pAddress를 사용하기로했다고 가정합니다.

할당 한 메모리에 실행하려면 특별한 권한이 필요할 수 있습니다. 즉, 원시 함수 데이터로 할당 한 메모리는 "데이터"로 표시됩니다. "데이터 실행 방지"는 환경에 따라이 문제를 막을 수 있습니다.

+0

고마워, 오타 였어. –