gargoyle: A memory scanning evasion technique


gargoyle title

gargoyle infographic

Building gargoyle

gargoyle is only implemented for 32-bit Windows (64-bit Windows on Windows is fine). You must have the following installed:

  • Visual Studio: 2017 Community is tested, but it may work for other versions.
  • Netwide Assembler v2.12.02 x64 is tested, but it may work for other versions. Make sure nasm.exe is on your path.

Clone gargoyle:

git clone

Open Gargoyle.sln, build, and run. There is some harness code in main.cpp that configures the following three components:

  • gargoyle stack trampoline, stack, and configuration (read/write memory on the heap)
  • gargoyle position independent code (PIC) that receives the ROP gadget/stack trampoline and runs arbitrary code
  • A ROP gadget. If you have mshtml.dllgargoyle will load it into memory and use it. If it is not available, you will have to tell gargoyle to allocate its own (3-byte) ROP gadget on the heap:
    // main.cpp
    auto use_mshtml{ true };
    auto gadget_memory = get_gadget(use_mshtml, gadget_pic_path);


Every 15 seconds, the gargoyle will pop up a message box. When you click ok, gargoyle sets up the tail calls to mark itself non-executable and to wait for the timer. For fun, use Sysinternals’s excellent VMMap tool to examine when gargoyle‘s PIC is executable. If a message box is active, the gargoyle will be executable. If it is not, gargoyle should not be executable. The PIC’s address is printed to stdout just before the harness calls into the PIC.

Copyright (C) 2017 Joshua Alfred Lospinoso