Je voudrais vider une mémoire de fonctions (void) dans un tableau d'octets (unsinged char[]
). En aval, une fonction fictive doit être pointée sur le tableau d'octets et la fonction fictive doit être exécutée.Mémoire de vidage d'une fonction
La fonction que je veux vider:
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
}
}
Dumping la mémoire:
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;
}
Lorsque l'on regarde à l'emplacement de mémoire DumpMemory
imprime sur la console, ollydbg montre une instruction JMP à cet endroit:
CPU Disasm
Address Hex dump Command Comments
00281627 $-/E9 044C0000 JMP CallMessageBoxExA
Est-ce le bon emplacement de mémoire, ou dois-je suivre le JMP?
saut de l'emplacement de mémoire conduit à:
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
POINTAGE la fonction factice au tableau d'octets:
void(*func_ptr)();
func_ptr = (void(*)()) &foo[0]; // make function point to foo[]
(*func_ptr)(); // Call the function
Est-ce la bonne façon de faire le point de la fonction factice au tableau d'octets?
À quel point la fin de la fonction est-elle atteinte? Dois-je simplement vérifier les différents opcodes de retour (C3 -> retour près de l'appelant, CB -> renvoyer loin à l'appelant, ...)? PS: Une solution simple (par exemple pas très élaborée) est préférée car je suis nouveau en C++.
Éditer: Je veux réaliser ceci dans un environnement de Windows.
[Ce n'est pas possible de manière portable.] (Http://en.wikipedia.org/wiki/Harvard_architecture) Si vous voulez un conseil spécifique à la plate-forme (il ressemble à Windows), spécifiez la plate-forme. –
Je recommanderais de développer vos compétences C++ avec quelque chose de beaucoup moins compliqué. –
Ce que vous cherchez à faire est une chose * TRES * puissante qui est utilisée par une poignée de développeurs dans le monde (surtout ceux qui écrivent des runtimes JIT pour les langues). Comme point de référence, dans mon propre cercle, en tant que développeur C++ de 10 ans, je suis le seul que je connaisse personnellement qui l'ait jamais essayé. –