1
votes

I am writing a code using inline asm with VC++ 2019 32bit. I have written a function to switch coroutine.This is the source code :

I tested it and it works well. The argument is a uintptr_t array that contains the register value. This function will exchagne register value except ebx.

The problem is the "Unhandled exception at 0x5514704E (pevm.dll) in tool.exe: 0x80000004: Single step.".

Register value : EAX = 00000246 EBX = 0019F5A0 ECX = E2F13240 EDX = 0019F5A0 ESI = 0019F3A8 EDI = 0019F3C8 EIP = 5514704E ESP = 0019F2BC EBP = 0019F2C0 EFL = 00000202

I can not understand why "pop eax" throw exception ? Maybe my code destroy some "internal data structure" and the program happened to stop here, like double free. Any suggestions to how to debug ?

inline __declspec(naked) void switchCoroutine(uintptr_t* vreg)
{
    //discard ebx
    __asm
    {
        push ebp
        mov ebp, esp
        //save 
        push eax
        //argument
        mov ebx, [ebp + 8]

        //exchange eflags 
        pushfd
        pop eax
        push[ebx]
        popfd
        mov[ebx], eax

        pop eax
        //exchange eax ,ecx,edx,esi,edi
        XCHG eax, [ebx + type int]
        xchg ecx, [ebx + 3 * type int]
        xchg edx, [ebx + 4 * type int]
        xchg esi, [ebx + 5 * type int]
        xchg edi, [ebx + 6 * type int]

        //exchange ebp,esp
        mov esp, ebp
        pop ebp
        xchg ebp, [ebx + 7 * type int]
        xchg esp, [ebx + 8 * type int]

        //go eip
        ret
    }
}

55147031 C2 04 00             ret         4  
--- No source file -------------------------------------------------------------
55147034 CC                   int         3  
55147035 CC                   int         3  
55147036 CC                   int         3  
55147037 CC                   int         3  
55147038 CC                   int         3  
55147039 CC                   int         3  
5514703A CC                   int         3  
5514703B CC                   int         3  
5514703C CC                   int         3  
5514703D CC                   int         3  
5514703E CC                   int         3  
5514703F CC                   int         3  
--- D:\code\c++\PEVM\core\vm\vdata.h -------------------------------------------
   643:     //discard ebx
   644:     __asm
   645:     {
   646:         push ebp
55147040 55                   push        ebp  
   647:         mov ebp, esp
55147041 8B EC                mov         ebp,esp  
   648:         //save 
   649:         push eax
55147043 50                   push        eax  
   650:         //argument
   651:         mov ebx, [ebp + 8]
55147044 8B 5D 08             mov         ebx,dword ptr [vreg]  
   652: 
   653:         //exchange eflags 
   654:         pushfd
55147047 9C                   pushfd  
   655:         pop eax
55147048 58                   pop         eax  
   656:         push[ebx]
55147049 FF 33                push        dword ptr [ebx]  
   657:         popfd
5514704B 9D                   popfd  
   658:         mov[ebx], eax
5514704C 89 03                mov         dword ptr [ebx],eax  
   659: 
   660:         pop eax
5514704E 58                   pop         eax    //HERE   **Unhandled exception at 0x5514704E (pevm.dll) in tool.exe: 0x80000004: Single step.**

   661:         //exchange eax ,ecx,edx,esi,edi
   662:         XCHG eax, [ebx + type int]
5514704F 87 43 04             xchg        eax,dword ptr [ebx+4]  
   663:         xchg ecx, [ebx + 3 * type int]
55147052 87 4B 0C             xchg        ecx,dword ptr [ebx+0Ch]  
   664:         xchg edx, [ebx + 4 * type int]
55147055 87 53 10             xchg        edx,dword ptr [ebx+10h]  
   665:         xchg esi, [ebx + 5 * type int]
55147058 87 73 14             xchg        esi,dword ptr [ebx+14h]  
   666:         xchg edi, [ebx + 6 * type int]
5514705B 87 7B 18             xchg        edi,dword ptr [ebx+18h]  
   667: 
   668:         //exchange ebp,esp
   669:         mov esp, ebp
5514705E 8B E5                mov         esp,ebp  
   670:         pop ebp
55147060 5D                   pop         ebp  
   671:         xchg ebp, [ebx + 7 * type int]
55147061 87 6B 1C             xchg        ebp,dword ptr [ebx+1Ch]  
   672:         xchg esp, [ebx + 8 * type int]
55147064 87 63 20             xchg        esp,dword ptr [ebx+20h]  
   673: 
   674:         //go eip
   675:         ret
55147067 C3                   ret  
--- No source file -------------------------------------------------------------
55147068 CC                   int         3  
55147069 CC                   int         3  
5514706A CC                   int         3  
5514706B CC                   int         3  
5514706C CC                   int         3  
5514706D CC                   int         3  
5514706E CC                   int         3  
5514706F CC                   int         3  
1
64 or 32 bit executable?Mike Vine
Updated. 32bit dll. blackshadow
Why not ebx? As far as I can tell from the calling conventions ebx needs to be saved.Mike Vine
popfd appears to set the Trace Flag (100h) which causes a trace interrupt after the next instruction, that is after mov [ebx], eaxecm

1 Answers

2
votes

At 0x5514704B you set EFLAGS. When it has TF flag set, a debug exception (#DB) will be generated by the CPU after next executed instruction. Next after popfd is mov[ebx], eax, thus the exception is generated after it's execution. Since #DB is a trap, eip points to address after the executed instruction, pop eax in your case.

Check if push[ebx] at 0x55147048 has TF bit set.