I am currently trying to bypass a CRC check, that exists inline on many places in an application to check if memory pages in the .text section have been modified.

CRC calculation routine Short explanation of the crc32 instruction:

Starting with an initial value in the first operand (destination operand), accumulates a CRC32 (polynomial 11EDC6F41H) value for the second operand (source operand) and stores the result in the destination operand.

Okay so: rsi contains the pointer of the next memory page that gets scanned and rax is the offset/counter. rdx is usually 200 (200 loops).

My goal: find where rsi is set. There has to be some instruction like mov rsi, next_memory_page_to_be_scanned.

Going further up in code: init for the loop vars

So here are the loop vars initialized (rdx,rax).

Going more up:first instruction in yellow for crc

So here is one of the things I am stuck: the yellow marked part seems to be the first instructions I can bp that gets executed before CRC_CHECK. I mean some other place obviously calls it, but I don't know how to find that place.

I tried to follow the return pointer: return bs

but the return pointer points to nothing basically. Breakpointing one instruction above (and [rcx], al) won't trigger the bp (seems to not have anything todo with the CRC check). How do I backtrace this further?

The value of rsi lays also not on the stack when I bp the CRC.


  • what about the two calls in the listing? Or the caller of this function? – Igor Skochinsky May 20 '18 at 13:58
  • the 2 calls are not called, the function itself is not called either, at least when i bp the function at the start it is not called (at least not for the CRC calculation). the first instruction that is executed here / that you can bp is movsd qword ... (the yellow marked part) – Lyan May 20 '18 at 14:38
  • can you show us the bytes for the opcodes and addresses? This and al,[rdx+r14*8-7BFAEFF1h] looks strange and I suspect some obfuscation going on which IDA maybe fails to recognize and shows you the wrong disassembly. – Paweł Łukasik May 21 '18 at 10:36
  • i.imgur.com/wGE8XX5.png here are the bytes of this function – Lyan May 22 '18 at 8:19
  • Are you sure that the code you are investigating is not a trap you have been guided to due to some Anti-Debug? Maybe you could modify the file with a hard written INT3 and see if the code arrives there without debugger. If yes, you could attach Ida at this point and see if it's the same as when debugging. – josh Jun 21 '18 at 19:45

Jumping off of Igor's suggestion of a trace, have you tried a break and trace via Cheat Engine yet? If not, consider the following:

  1. Whether via byte array (requiring an AOB scan first; make sure you select read/write memory), module+offset, or symbol name (if applicable), find your way to the crc32 edi, qword ptr [rsi+rax*8] instruction in Cheat Engine's disassembler (the top half of the Memory Viewer).
  2. Right-click on the instruction and choose Break and trace instructions.
  3. In the subsequent window, check Save stack snapshots and Step over instead of single step, then click OK.
  4. Once the Tracer window populates with your trace, right-click within it and choose Expand all.
  5. Scroll to the farthest branch of the tree, of which the top-most instruction should be your crc32 edi, qword ptr [rsi+rax*8] instruction.
  6. Click the Stack button and keep the window that opens (Stack View), beside the Tracer window.

Now work your way down the list of recorded instructions (which will take you back up through callers with each branch). You can watch the registers on the right-hand side, as well as the stack via the Stack View window. You can double-click on any instruction in the Tracer to take you to that instruction in the disassembler, where you can then read up through sub-routines from callers.

If there isn't enough branching for you, then run the trace again and change the initial number of instructions traced from 1000 to whatever you'd like. Also, if you find your way into a caller's sub-routine and there are other calls from within it that you'd like to drill down into, simply run another break/trace at some point before the call, then do not select (or de-select, if it's already selected) Step over instead of single step.

Finally as another tip, in the Memory Viewer, if you run Tools -> Dissect Code, you can then select the base module and any other dependencies to run a bunch of automated tasks on, like finding all referenced strings and functions, and finding all xrefs to all routines!

The xrefs one is great for being able to head to the prologue of any given function (right-click on any instruction and choose Select current function, then scroll to the top) and quickly see how many callers there are (of which you can double-click any of to go to them).

This allows you to quickly see if a function is shared, thus potentially acting as a pivot point to either patch with a ret (or however you'd prefer to patch), or allowing you to choose which specific call instructions to that particular function you'd like to individually patch.

| improve this answer | |

It sounds like the program is using some kind of obfuscation. You probably should step through it from the beginning or record an instruction trace to see how it ends up executing these instructions.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.