Author | Message | Time |
---|---|---|
Myndfyr | I'm toying around at work with VC++ and runtime code re-writing (for code protection), and wanted to know a few things... 1.) Will I need to mark the virtual code segment readable/writeable? I'm trying to just print out memory byte-by-byte and I got the following runtime error: [code] First-chance exception at 0x0041b4a2 in CrackMe1.exe: 0xC0000005: Access violation reading location 0x0025fb58. Unhandled exception at 0x0041b4a2 in CrackMe1.exe: 0xC0000005: Access violation reading location 0x0025fb58. [/code] 2.) Am I using the right types? Here's what I have so far (types can be inferred, these are the main functions that I'm using): [code] int _tmain(int argc, _TCHAR* argv[]) { char *psz_inbuf; DWORD *pnLabelLoc; DWORD *pnEndLoc; DWORD nDiff; __asm push ecx psz_inbuf = new char[20]; do { cout << "Enter password: " << endl; psz_inbuf = gets(psz_inbuf); } while (psz_inbuf == NULL); cout << "Memory location: " << &psz_inbuf << endl; _asm { xor ecx, ecx mov ecx, dword ptr checking_code mov pnLabelLoc, ecx mov ecx, dword ptr end_checking_code mov pnEndLoc, ecx } cout << "Label location: " << pnLabelLoc << endl; cout << "End location: " << pnEndLoc << endl; nDiff = (BYTE)pnEndLoc - (BYTE)pnLabelLoc; cout << "Difference: " << nDiff << endl; print( (BYTE*)pnLabelLoc, nDiff ); getchar(); __asm { checking_code: xor ecx, ecx inc ecx end_checking_code: inc ecx } __asm pop ecx return 0; } inline void print(const BYTE *pMem, const DWORD nLen) { DWORD nMem, nVal; cout << "Data from pnLabelLoc to pnEndLoc:" << endl; __asm push edx for (DWORD i = 0; i < nLen; i++) { __asm mov edx, pMem __asm add edx, i __asm mov nMem, edx __asm xor edx, edx __asm mov dl, byte ptr [pMem + i] __asm mov nVal, edx cout << "[" << nMem << "]: " << nVal << endl; } __asm pop edx } [/code] And this is the complete output: [code] Enter password: sgfe Memory location: 0012FED4 Label location: 0041B374 End location: 0041B377 Difference: 3 Data from pnLabelLoc to pnEndLoc: [/code] I don't know whether or not I should be taking care of storing register contents. All I know is that when I took assembly, they told us that we should store register contents. I realize I'm using C as opposed to pure assembly, so if I shouldn't be doing that, give me a heads-up. This is the offending line, from print(BYTE *, DWORD): [code] __asm mov dl, byte ptr [pMem + i] [/code] So I assume that code memory is not readable? Basically, I want to print the memory byte-by-byte between the checking_code and end_checking_code labels. I wanted to do this as an inline function so I could look at the result disassembly and see if it is any more difficult to read. Of course, that assumes the compiler obeys inline. The ultimate goal is to be able to read and write to arbitrary memory within the program's virtual memory space -- not violating any kernel rules, but being able to rewrite code on the fly as well as data. Any thoughts? | March 31, 2005, 2:11 AM |
Adron | [quote author=MyndFyre link=topic=11109.msg106448#msg106448 date=1112235111] 1.) Will I need to mark the virtual code segment readable/writeable? [/quote] In Win32 it is readable but not writeable by default. [quote author=MyndFyre link=topic=11109.msg106448#msg106448 date=1112235111] This is the offending line, from print(BYTE *, DWORD): [code] __asm mov dl, byte ptr [pMem + i] [/code] So I assume that code memory is not readable? [/quote] It is readable. You're just not reading the right memory. You get an error reading from 0x25fb58, and that's not the location of your code. I don't see why you're doing this in assembly, as it would make much more sense to do it in plain C/C++. Your problems are with your implementation of this in assembler. For one, yes, you should save most registers. But you should save them before you modify them and restore them before you return to executing C/C++ code. As you have it now, you are modifying esp and edx and then executing C/C++ code before you have restored them. Rewrite print without any assembler use and it'll work much better. I don't know exactly what is wrong with your print function - could be that edx/esp are used by the compiler for something and you're messing it up, or it could be the way "mov dl, byte ptr [pMem + i]" is written. It's not obvious to me why you'd get a pointer so far into nothingness but it probably would be if I was looking at the generated code for it. What you're doing there is wrong unless both pMem and i are available in registers and even then, the compiler probably won't do what you're expecting of it. | March 31, 2005, 8:44 AM |
Myndfyr | OK -- I updated the print function to remove the inline assembly. Here it is: [code] inline void print(const BYTE *pMem, const DWORD nLen) { cout << "Data from pnLabelLoc to pnEndLoc:" << endl; for (DWORD i = 0; i < nLen; i++) { cout << "[" << ((DWORD)(pMem + i)) << "]: " << ((int)*(pMem + i)) << endl; } } [/code] and here is the revised output: [code] Enter password: dgzh Memory location: 0012FED4 Label location: 0041B364 End location: 0041B367 Difference: 3 Data from pnLabelLoc to pnEndLoc: [4305764]: 51 [4305765]: 201 [4305766]: 65 [/code] Intuition tells me that the first memory location is in the data segment, where it's storing the string. Also, cout is data-type specific, so both values are in decimal instead of hex -- the memory location is correct, if I am indeed obtaining the address of the labels. And I couldn't pass the pointer to cout, as it would try to print the data like a string. So I cast it back to a numeric value. Because of the casts, I'm getting this warning: [code]warning C4311: 'type cast' : pointer truncation from 'const BYTE *' to 'DWORD'[/code] But it appears to work. Adron -- how can I mark a section writeable? [edit] I did an opcode lookup using the IA32 manual #2. The output was: [4305764]: 51 [4305765]: 201 [4305766]: 65 51 = 0x33, which is XOR Gb, Ev. This is what the manual says for E notes: [quote]A ModR/M byte follows the opcode and specifies the operand. The operand is either a general-purpose register or a memory address. If it is a memory address, the address is computed from a segment register and any of the following values: a base register, an index register, a scaling factor, a displacement.[/quote] Of G: [quote]The reg field of the ModR/M byte selects a general register (for example, AX (000)).[/quote] The 201 value, or 0xc9, is represented 1100 1001 in binary. Split as the ModR/M byte -- 11 001 001, the middle value indicates that it's ECX. I can't find the meaning of the rest of the bits -- any ideas? Finally, 65, or 0x41, is easily looked up as INC ECX. So it turns out I *was* looking at the right spot in memory or, short of that, got REALLY lucky! | April 1, 2005, 2:26 AM |
Arta | VirtualProtect/VirtualProtectEx, with PAGE_EXECUTE_READWRITE. I set mine back to PAGE_EXECUTE_READ when I'm done, because making executable pages read-only is a sensible precaution. | April 1, 2005, 2:30 AM |
Adron | [quote author=MyndFyre link=topic=11109.msg106668#msg106668 date=1112322392] Intuition tells me that the first memory location is in the data segment, where it's storing the string. [/quote] It's actually in the stack, where it's storing the pointer to the string. [quote author=MyndFyre link=topic=11109.msg106668#msg106668 date=1112322392] Split as the ModR/M byte -- 11 001 001, the middle value indicates that it's ECX. I can't find the meaning of the rest of the bits -- any ideas? [/quote] Mod = 11: Both operands are registers Reg = 001: CL/CX/ECX R/M = 001: CL/CX/ECX | April 1, 2005, 8:39 AM |