memtst.s

.globl _WinMain@16

/*
 * .text section
 */

.text

/*
 * void vrtqry(void *memaddr,MEMORY_BASIC_INFORMATION *membasicinfoaddr) {
 */
vrtqry:
        /*
         * A: Standard function prologue to create a stack frame pointer
         */
        pushl   %ebp
        movl    %esp,%ebp

        /*
         * B: Save the registers that either we modify,
         * or that _VirtualQuery@12 modifies
         */
        pushl   %eax
        pushl   %ecx
        pushl   %edx

        /*
         * C: call VirtualQuery(memaddr,membasicinfoaddr)
         */
        pushl   $0x1c
        pushl   0xc(%ebp)
        pushl   0x8(%ebp)
        call    _VirtualQuery@12

        /*
         * D: Restore the registers
         */
        popl    %edx
        popl    %ecx
        popl    %eax

        /*
         * E: Standard function epilogue
         */
        movl    %ebp,%esp
        popl    %ebp
        ret
/*
 * }
 */

/*
 * F: _WinMain@16()
 *     Execution begins here
 *     (we don't care about the arguments)
 */
_WinMain@16:
        pushl   %ebp
        movl    %esp,%ebp

        /*
         * G: Leave space on the stack for a MEMORY_BASIC_INFORMATION 
         * structure. 0x28 is the structure's size
         */
        subl    $28,%esp    /* sizeof(MEMORY_BASIC_INFORMATION) */

        pushl   $0x0    /* this is used to indicate second iteration of the loop and terminate it */

        /*
         * H: Popular malware trick to find the address of the next 
         * instruction. In this case, the address of the 'popl %eax' 
         * instruction at nxtinstr.
         */
        call    nxtinstr
nxtinstr:
        /*
         * I: pop the return address of the call instruction off the stack 
         * and in to the eax register. The return address of a call 
         * instruction is the address of the instruction immediately 
         * following the call which in this case is the address of the 
         * following 'popl %eax' instruction, at the address defined by 
         * the label 'nxtinstr'.
        */
        popl    %eax

        /*
         * J: The following 'nop' instruction is a place holder.
         * Little does it know that we are going to replace it with an
         * 'inc %ebx' instruction. I suspect that if it did, it wouldn't 
         * be sitting here so calmly.
         */
        nop

        /*
         * K: Call our vryqry() function to get base address and current 
         * permissions of the memory page containing the 'popl %eax' 
         * instruction at nxtinstr.
         */

        /*
         * L: First, push the address of our MEMORY_BASIC_INFORMATION 
         * structure on the stack.
         * This will be the second parameter (they are pushed in reverse 
         * order) to our vrtqry() function above.
         */
        lea     -28(%ebp),%edx
        pushl   %edx                    /* &MEMORY_BASIC_INFORMATION */

        /*
         * M: push the return address from the call instruction.
         * That is, the address of the instruction at 'nxtinstr', and the 
         * address for which we are seeking the information.
         * This address will be passed as the first argument to our 
         * vrtqry() function.
         */
        pushl   %eax
        call    vrtqry

        /*
         * N: Remove our arguments from the stack, as our vrtqry() 
         * function doesn't
         */
        addl    $0x8,%esp

        /*
         * O: Save the registers modified by printf()
         */
        pushl   %eax
        pushl   %edx                    /* changed by printf() */

        /*
         * P: Print out some of the fields from the 
         * MEMORY_BASIC_INFORMATION structure.
         * call printf("BaseAddress: 0x%x\nAllocationBase: 0x%x\nAllocationProtect: 0x%x\nProtect: 0x%x\nType: 0x%x\n",BaseAddress,AllocationBase,State,Protect,Type)
         */
        addl    $0x18,%edx  /* &MEMORY_BASIC_INFORMATION.Type */
        pushl   (%edx)
        subl    $0x4,%edx   /* &MEMORY_BASIC_INFORMATION.Protect */
        pushl   (%edx)
        subl    $0x4,%edx   /* &MEMORY_BASIC_INFORMATION.State */
        pushl   (%edx)
        subl    $0xc,%edx   /* &MEMORY_BASIC_INFORMATION.AllocationBase */
        pushl   (%edx)
        subl    $0x4,%edx   /* &MEMORY_BASIC_INFORMATION.BaseAddress */
        pushl   (%edx)
        pushl   $fmt_vrtqry       /* address of format string */
        call    _printf
        addl    $0x18,%esp        /* Remove arguments from the stack */

        /*
         * Q: Restore registers
         */
        popl    %edx
        popl    %eax

        /*
         * R: Call _VirtualProtect@16() to modify the page permissions by 
         * adding WRITE
         * %edx points to start of MEMORY_BASIC_INFORMATION structure
         *     .Protect needs to change from 0x20 (PAGE_EXECUTE_READ) to 
         *     0x40 (PAGE_EXECUTE_READWRITE)
         */
        // pushl        %eax               /* save value of eax register */

        // subl $0x4,%esp     /* leave space on stack for lpflOldProtect */
        // pushl        %esp                   /* addr of lpflOldProtect */
        // pushl        $0x40                  /* flNewProtect */
        // pushl        $0x0fff                /* dwSize */
        // pushl        (%edx)                 /* lpAddress */
        // call _VirtualProtect@16

        /*
         * S: call printf() to print value returned from VirtualProtect() 
         * and flOldProtect
         */

        /* old flProtect will be on stack */
        // pushl %eax       /* BOOL value returned from VirtualProtect() */
        // pushl $fmt_result
        // call _printf
        // addl $0xc,%esp

        // popl %eax                    /* restore value of eax register */

        /*
         * T: Call getchar() to pause the process
         * to allow a kernel debugger to be attached
         */
        pushl   %eax
        call    _getchar
        popl    %eax

        pushl   %eax  /* save eax register as printf() returns number of characters printed in eax, which will clobber it */

        /*
         * U: call printf() to print address in eax register
         * and the contents of the ebx register
         */
        pushl   %ebx
        pushl   %eax
        pushl   $fmtstr2
        call    _printf
        addl    $0xc,%esp

        popl    %eax                    /* restore eax register */

        /*
         * V: Check the contents of the eax register
         * On the first iteration, this will be the address of the 'popl 
         * %eax' instruction at nxtinstr:
         * On the second iteration, this will be the 0 that we push on to 
         * the stack near the start of _WinMain@16()
         */
        cmpl    $0x0,%eax
        je      skiprpt

        /*
         * W: If eax is not zero, then modify the 'nop' instruction to 
         * 'inc %ebx' and loop back to the address in eax.
         */

        /* Sit tight -- this may hurt a little */
        movb    $0x43,0x1(%eax)

        /* X: jump back to nxtinstr: */
        jmp     *%eax
skiprpt:

        /* Y: return 0 */
        xor     %eax,%eax
        leave
        ret

/*
 * Z: .data section
 */

.data
fmtstr: .ascii "%d\n"
fmtstr2: .ascii "nop is at 0x%x\n%%ebx: 0x%x\n"
fmt_vrtqry: .ascii "BaseAddress: 0x%x\nAllocationBase: 0x%x\nAllocationProtect: 0x%x\nProtect: 0x%x\nType: 0x%x\n"
fmt_result: .ascii "Returned: %d\nflOldProtect: 0x%x\n"

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s