I recently came across a Keygen-Me challenge that turned out to be surprisingly well protected with a simple timing technique. I thought at first it was simply designed to defeat step-by-step debugging. But it was capable of defeating several QEMU based virtual machine based tracing tools and Intel's PIN tracing tool. Let's have a look.
An rdtsc instruction, some more code, another rdtsc instruction and a check. The rdtsc instruction gives access to the processor's Time Stamp Counter:
So depending on whether the time counter on the virtual machine is virtualized or passed through, it can be detected.
Standard qira, when executing this program, causes it to careen off into a crash...
$ qira ./theexecutable****** starting WEB SERVER on 0.0.0.0:3002*** using base 0 for 0on 0 going from 1 to 379490...*** WARNING, changing segment 0x8048000 134520300done 163.008000 mson 0 going from 379490 to 697964...done 156.404000 mson 0 going from 697964 to 1026219...done 169.573000 mson 0 going from 1026219 to 1399111...done 194.284000 mson 0 going from 1399111 to 1831883...done 237.863000 mson 0 going from 1831883 to 2338968...done 293.269000 mson 0 going from 2338968 to 2953999...done 378.872000 mson 0 going from 2953999 to 3599337...qemu: uncaught target signal 11 (Segmentation fault) - core dumpeddone 477.153000 mson 0 going from 3599337 to 3742593...done 91.464000 msEven instrumentation such as Intel PIN can be detected, if they slow down the code too much.
$ qira --pin ./theexecutableA: qirapin.cpp: ThreadFini: 925: qirapin scratch register ended up with a weird value.################################################################################## STACK TRACE################################################################################??? at qirapin.so+0x2f452 ??? at qirapin.so+0x19bbf ??? at qirapin.so+0x93a65 ??? at /home/ubuntu/Documents/qiraold/tracers/pin/pin-3.7-97619-g0d0c92f4f-gcc-linux/ia32/bin/pinbin+0x28ac82 _ZN8LEVEL_VM19VM_SHUTDOWN_MANAGER16CompleteShutdownEPNS_9VM_THREADENS_16TERMINATE_REASONEj+0x61 at /home/ubuntu/Documents/qiraold/tracers/pin/pin-3.7-97619-g0d0c92f4f-gcc-linux/ia32/bin/pinbin+0x26e131 _ZN8LEVEL_VM19VM_SHUTDOWN_MANAGER10DoShutdownEPNS_9VM_THREADENS_16TERMINATE_REASONEj+0x2dd at /home/ubuntu/Documents/qiraold/tracers/pin/pin-3.7-97619-g0d0c92f4f-gcc-linux/ia32/bin/pinbin+0x2716ad _ZN8LEVEL_VM11VM_ShutdownEPNS_9VM_THREADENS_16TERMINATE_REASONEj+0xa4 at /home/ubuntu/Documents/qiraold/tracers/pin/pin-3.7-97619-g0d0c92f4f-gcc-linux/ia32/bin/pinbin+0x271b24 _ZN8LEVEL_VM12SIGNALS_IMPL18DeliverFatalSignalEjiPKNS_7CONTEXTEb+0x94 at /home/ubuntu/Documents/qiraold/tracers/pin/pin-3.7-97619-g0d0c92f4f-gcc-linux/ia32/bin/pinbin+0x2fd7e4 _ZN8LEVEL_VM12SIGNALS_IMPL12FilterSignalEPNS0_15PER_THREAD_DATAEjPNS_8EMULATORERKN5PINVM7VSIGNALEPKN10LEVEL_BASE14EXCEPTION_INFOEPSt4listIS6_SaIS6_EEb+0x777 at /home/ubuntu/Documents/qiraold/tracers/pin/pin-3.7-97619-g0d0c92f4f-gcc-linux/ia32/bin/pinbin+0x3011a7 _ZN8LEVEL_VM12SIGNALS_IMPL30CapturePendingSignalsAndFilterEPNS0_15PER_THREAD_DATAEjPNS_8EMULATOREPKN5PINVM7VSIGNALEPKN10LEVEL_BASE14EXCEPTION_INFOEPSt4listIS6_SaIS6_EEb+0x536 at /home/ubuntu/Documents/qiraold/tracers/pin/pin-3.7-97619-g0d0c92f4f-gcc-linux/ia32/bin/pinbin+0x301ad6 _ZN8LEVEL_VM12SIGNALS_IMPL20HandlePendingSignalsEPNS0_15PER_THREAD_DATAEjPNS_8EMULATOREPKN5PINVM7VSIGNALEPKN10LEVEL_BASE14EXCEPTION_INFOEb+0x8f at /home/ubuntu/Documents/qiraold/tracers/pin/pin-3.7-97619-g0d0c92f4f-gcc-linux/ia32/bin/pinbin+0x30833f _ZN8LEVEL_VM12SIGNALS_IMPL19InternalHandlerSyncEiP7siginfoPN5PINVM11ISIGCONTEXTEPPKNS_14SCT_ATTRIBUTESEPNS_5PCTXTEPj+0x582 at /home/ubuntu/Documents/qiraold/tracers/pin/pin-3.7-97619-g0d0c92f4f-gcc-linux/ia32/bin/pinbin+0x30a592 _ZN8LEVEL_VM12SIGNALS_IMPL20HandlePhysicalSignalEP7siginfoPN5PINVM11ISIGCONTEXTE+0x22e at /home/ubuntu/Documents/qiraold/tracers/pin/pin-3.7-97619-g0d0c92f4f-gcc-linux/ia32/bin/pinbin+0x30af2e _ZN5PINVM25SIGNAL_DETAILS_LINUX_IA3215InternalHandlerEiPvS1_+0x6d at /home/ubuntu/Documents/qiraold/tracers/pin/pin-3.7-97619-g0d0c92f4f-gcc-linux/ia32/bin/pinbin+0x39c87d Pin: pin-3.7-97619-0d0c92f4fCopyright (c) 2003-2018, Intel Corporation. All rights reserved.Pin app terminated abnormally due to signal 6.Sure enough, it was the timing test that caused the crash:
Lets try the rr Record and Replay Framework by Mozilla:
$ rr record ./theexecutablerr: Saving execution to trace directory `/home/jan/.local/share/rr/KeygenMe-0'.Segmentation faultIt is vulnerable to this protection as well. gdbgui supports stepping forward and backwards through the trace.
$ gdbgui --rrthen inside of gdb we can execute up to the crash and step back a few instructions.
And sure enough, it's the timing test again...
The tools work fine after patching out the timing test.
The exectuable had more protections, and it was a great example of how useful qira is when it works.