0

thank you for taking your time to read this.

I am trying to read an udp bitstream from a program, just for fun and for gaining knowledge which may be usefull for others later on. I found https://github.com/zeroKilo/BFP4FToolsWV/blob/master/Zlib122_2010/zlib122/UDPMon.h which shows a nice sample for a game called Battlefield: Play4Free.

I have tried to implement it as follows:

DWORD readReturn;
DWORD readBuff;
DWORD readSize;
DWORD readEAX;
DWORD writeBuff;
DWORD writeSize;
DWORD writeEAX;

void PrintBitRead()
{
    DWORD tmpReturn = readReturn;
    DWORD tmpSize = readSize / 8;
    if (readSize % 8 != 0)
        tmpSize++;
    BYTE* tmpBuff = (BYTE*)readBuff;
    char* tmpHex = (char*)calloc(3, 1);
    for (int i = 0; i < tmpSize; i++)
    {
        sprintf(tmpHex, "%02X", tmpBuff[i]);
    }
    free(tmpHex);
    readReturn = tmpReturn;
}

void __declspec(naked) BitStreamRead()
{
    _asm
    {
        //save eax
        mov readEAX, eax;
        //change return
        mov eax, [esp];
        mov readReturn, eax;
        mov eax, label_return;
        mov[esp], eax;
        //save buffer address
        mov eax, [esp + 4];
        mov readBuff, eax;
        //save buffer size
        mov eax, [esp + 8];
        mov readSize, eax;
        //restore eax
        mov eax, readEAX;
        //rest of overwritten asm
        push ebp;
        mov ebp, esp;
        mov edx, [ebp + 0x08];
        push 0x007A340E;
        ret;
    label_return:
        //save regs
        pushad;
        //was success?
        test eax, eax;
        jz label_skip;
        //save to log
        call PrintBitRead;
    label_skip:
        //restore regs
        popad;
        //restore return
        push readReturn;
        ret;
    }
}

BitStreamRead is referenced to by the windows detours library:

DetourFunction((PBYTE)0x7A340B, (PBYTE)BitStreamRead);

I provide a static address because I disabled ASLR in the executable. When looking at the original function definition we see:

.text:007A340B var_10          = dword ptr -10h
.text:007A340B var_C           = dword ptr -0Ch
.text:007A340B var_8           = dword ptr -8
.text:007A340B var_4           = dword ptr -4
.text:007A340B arg_0           = dword ptr  8
.text:007A340B arg_4           = dword ptr  0Ch
.text:007A340B
.text:007A340B                 push    ebp
.text:007A340C                 mov     ebp, esp
.text:007A340E                 mov     edx, [ebp+arg_0]
.text:007A3411                 sub     esp, 10h
.text:007A3414                 push    ebx
.text:007A3415                 mov     ebx, ecx
.text:007A3417                 test    edx, edx
.text:007A3419                 jnz     short loc_7A3422
.text:007A341B
.text:007A341B loc_7A341B:                             ; CODE XREF: BitStreamRead+1C↓j
.text:007A341B                 xor     al, al
.text:007A341D                 jmp     loc_7A34C9
.text:007A3422 ; ---------------------------------------------------------------------------
.text:007A3422
.text:007A3422 loc_7A3422:                             ; CODE XREF: BitStreamRead+E↑j
.text:007A3422                 mov     ecx, [ebp+arg_4]
.text:007A3425                 test    ecx, ecx
.text:007A3427                 jz      short loc_7A341B
.text:007A3429                 mov     eax, [ebx+10h]
.text:007A342C                 push    esi
.text:007A342D                 lea     esi, [eax+ecx]
.text:007A3430                 cmp     esi, [ebx+18h]
.text:007A3433                 jbe     short loc_7A3447
.text:007A3435                 mov     byte ptr [ebx+20h], 1
.text:007A3439                 mov     dword ptr [ebx+24h], 2
.text:007A3440                 xor     al, al
.text:007A3442                 jmp     loc_7A34C8
.text:007A3447 ; ---------------------------------------------------------------------------
.text:007A3447
.text:007A3447 loc_7A3447:                             ; CODE XREF: BitStreamRead+28↑j
.text:007A3447                 push    edi
.text:007A3448                 mov     esi, eax
.text:007A344A                 shr     esi, 3
.text:007A344D                 add     esi, [ebx]
.text:007A344F                 and     eax, 7
.text:007A3452                 push    8
.text:007A3454                 pop     edi
.text:007A3455                 sub     edi, eax
.text:007A3457                 mov     [ebp+var_4], edx
.text:007A345A                 mov     dl, [esi]
.text:007A345C                 inc     esi
.text:007A345D                 cmp     ecx, 8
.text:007A3460                 mov     [ebp+var_10], eax
.text:007A3463                 mov     [ebp+var_8], ecx
.text:007A3466                 jl      short loc_7A349C
.text:007A3468                 mov     eax, ecx
.text:007A346A                 shr     eax, 3
.text:007A346D                 mov     [ebp+var_C], eax
.text:007A3470                 shl     eax, 3
.text:007A3473                 sub     ecx, eax
.text:007A3475                 mov     [ebp+var_8], ecx
.text:007A3478
.text:007A3478 loc_7A3478:                             ; CODE XREF: BitStreamRead+8C↓j
.text:007A3478                 mov     al, [esi]
.text:007A347A                 mov     cl, byte ptr [ebp+var_10]
.text:007A347D                 shr     dl, cl
.text:007A347F                 mov     byte ptr [ebp+arg_0+3], al
.text:007A3482                 mov     ecx, edi
.text:007A3484                 shl     al, cl
.text:007A3486                 inc     esi
.text:007A3487                 or      dl, al
.text:007A3489                 mov     eax, [ebp+var_4]
.text:007A348C                 inc     [ebp+var_4]
.text:007A348F                 dec     [ebp+var_C]
.text:007A3492                 mov     [eax], dl
.text:007A3494                 mov     dl, byte ptr [ebp+arg_0+3]
.text:007A3497                 jnz     short loc_7A3478
.text:007A3499                 mov     ecx, [ebp+arg_4]
.text:007A349C
.text:007A349C loc_7A349C:                             ; CODE XREF: BitStreamRead+5B↑j
.text:007A349C                 cmp     [ebp+var_8], 0
.text:007A34A0                 jle     short loc_7A34C2
.text:007A34A2                 mov     al, [esi]
.text:007A34A4                 mov     ecx, edi
.text:007A34A6                 shl     al, cl
.text:007A34A8                 mov     cl, byte ptr [ebp+var_10]
.text:007A34AB                 shr     dl, cl
.text:007A34AD                 mov     ecx, [ebp+var_8]
.text:007A34B0                 or      al, dl
.text:007A34B2                 mov     dl, 1
.text:007A34B4                 shl     dl, cl
.text:007A34B6                 mov     ecx, [ebp+var_4]
.text:007A34B9                 dec     dl
.text:007A34BB                 and     al, dl
.text:007A34BD                 mov     [ecx], al
.text:007A34BF                 mov     ecx, [ebp+arg_4]
.text:007A34C2
.text:007A34C2 loc_7A34C2:                             ; CODE XREF: BitStreamRead+95↑j
.text:007A34C2                 add     [ebx+10h], ecx
.text:007A34C5                 mov     al, 1
.text:007A34C7                 pop     edi
.text:007A34C8
.text:007A34C8 loc_7A34C8:                             ; CODE XREF: BitStreamRead+37↑j
.text:007A34C8                 pop     esi
.text:007A34C9
.text:007A34C9 loc_7A34C9:                             ; CODE XREF: BitStreamRead+12↑j
.text:007A34C9                 pop     ebx
.text:007A34CA                 leave
.text:007A34CB                 retn    8

So I first try to save the address of the buffer and then print it out. But it only prints 0700 and then it crashes. To be honest, I am quite new to assembly coding and I hope you dont mind me asking a question that may be stupid.

I thank you for your time in reading this question and if I need to provide any more information I will provide it as soon as possible!

  • @FrançoisAndrieux I gave it that tag since I used some C++ code to print out the buffer. But you are right, its not most relevant – anasmcoder Aug 22 '18 at 21:33
  • What do you expect `push 0x007A340E` / `ret` to do? Is there some reason you expect there to be executable code at that address? (And why not `jmp` there, unless you need to make position-independent code for ASLR or something? But if you have ASLR, how do you know what's at that absolute address?) – Peter Cordes Aug 22 '18 at 21:45
  • Also, there are no references to `BitStreamRead`. What calls it? Where exactly does your code crash: use your debugger to find what instruction faults, and why, then add that to the question. – Peter Cordes Aug 22 '18 at 21:48
  • @PeterCordes thank you, I updated the question. As for push 0x007A340E. I expect it to return control to the original function.But I am unsure, to be honest I just copied a piece of code from github without fully understanding what it does and tried to change it so it would work for me... – anasmcoder Aug 22 '18 at 22:10
  • `ret` is basically `pop EIP`, so push/ret is an inefficient absolute jump which hurts performance by unbalancing the return-address predictor stack. http://blog.stuffedcow.net/2018/04/ras-microbenchmarks/. So unless a `0x007A340E` happens to be the address after a `call` instruction, no it's not returning to the caller. And if it was, you should just use the return address passed by your caller. – Peter Cordes Aug 22 '18 at 22:15
  • Interesting, a quick debug with ida gives The instruction at 0x7A340E referenced memory at 0xFFFFFFFF. The memory could not be read (exc.code c0000005, tid 1724) so it seems I am doing something very wrong with those offsets. My receiver that should receive the buffer doesnt receive anything but the still tries to push that offset. But I should try to use jmp with that offset instead – anasmcoder Aug 22 '18 at 22:25
  • Why do you think execution should go to `0x7A340E` at all, instead of back to the caller of your function? What's there? And what does that have to do with parsing a UDP bitstream? And why are you using static storage for `readReturn` and others, instead of keeping them on the stack? – Peter Cordes Aug 22 '18 at 22:27
  • So the function can continue parsing the packet and return it to the handler. The function I am trying to detour is a function in a gameserver which reads udp packets from the game client. I want to get the raw hex of this packet(since it gets packed in bits, encrypted and compressed before its sent) the only place where it is fully visible is in that function. Debugging showed that the actuall error happenes on .text:007A3492 mov [eax], dl Where eax is a pointer to the current function – anasmcoder Aug 22 '18 at 22:31

0 Answers0