- The file format contains many fields of type DWORD. There was given a sample file. I made as many copies of the sample file as many DWORD fields it had. I crafted each sample to have
0x41414141in a DWORD field. Only one DWORD field was changed per sample so all DWORD fields were covered by the change.
- I wrote a PinTool, called TraceAndWatch, for this occassion that checks the value of the general registers before every instruction is executed. It shows memory state including disassembly of the instruction when a register value matches
- I executed the application using TraceAndWatch and let the application to parse the first sample containing
0x41414141. TraceAndWatch produced a log and I saw what instructions using
- In static disassembly code, I located the instructions using
0x41414141and saw arithmetic and comparison operations with that value.
- In some cases I realized I can enter to other code path by changing
0x41414141in the sample to other value e.g. to signed value like
0x88888888. And re-run the test with TraceAndWatch specifying to trace and watch instructions using
- I executed this manual test on all the samples produced earlier.
The following weaknesses can be audited by this approach.
CWE-839: Numeric Range Comparison Without Minimum Check
CWE-195: Signed to Unsigned Conversion Error
CWE-682: Incorrect Calculation
CWE-190: Integer Overflow or Wraparound
CWE-680: Integer Overflow to Buffer Overflow
CWE-191: Integer Underflow (Wrap or Wraparound)
Final NotesThis is a generic, and quick way to locate comparison and arithmetic of integers.
TraceAndWatch doesn't track other than general registers so you can loose track of integers when value copied to, like, SSE register.
When arithmetic is performed on the value e.g.
0x41414141is multiplied by 2, you need to set TraceAndWatch to look for
0x82828282not to loose the tracking.
TraceAndWatch is available for download on my OneDrive space. If you use it you may contact me with your experience.