Seemingly wrong instruction pointer reported by VS2017 - windows

Edit:
I've investigated more, and the problem reported below seems to happen only when I use Visual Studio 2017 to pause the process. It also seems that when rip is pointing to an invalid location, it's always a +1 byte offset from the correct instruction start.
Also, for context, this is a large C++ project with lots of dlls, some compiled with MSVC 2015, the rest with icc (intel compiler 2017). This is run in a python process using boost C++/python bindings.
Original post:
I am pausing my program randomly to see what are my threads doing during some heavy computation.
Note that I am not debugging a crash, resuming the program works fine.
Howver the VS debugger is sometimes unable to dissassemble the machine code.
For instance, on one thread where rip=000007FE8B048EE2, it shows this:
000007FE8B048EDE ?? ??
000007FE8B048EDF ?? ??
000007FE8B048EE0 ?? ??
000007FE8B048EE1 ?? ??
}
if (params.derandomize) {
000007FE8B048EE2 adc ebp,eax
GetRNG().Seed(id);
000007FE8B048EE4 pop rax
000007FE8B048EE5 wait
000007FE8B048EE6 adc byte ptr [rax],al
000007FE8B048EE8 mov rcx,rax
The decoded x86 instructions also seem wrong (adc, pop, wait, adc ??), so I tried to attach WinDBG as well (non invasive mode):
0:019> u rip
somedll!<lambda239>::operator()+0x132:
000007fe`8b048ee2 13e8 adc ebp,eax
000007fe`8b048ee4 58 pop rax
000007fe`8b048ee5 9b wait
000007fe`8b048ee6 1000 adc byte ptr [rax],al
000007fe`8b048ee8 4889c1 mov rcx,rax
000007fe`8b048eeb 8b9570080000 mov edx,dword ptr [rbp+870h]
000007fe`8b048ef1 e8fa911000 call somedll!bla::bla::blabla::blabla::Seed (000007fe`8b1520f0)
000007fe`8b048ef6 4c8ba5b0080000 mov r12,qword ptr [rbp+8B0h]
Ok, it's the same garbage...
But then I tried to dissassemble from an address slightly above rip:
0:019> u rip-30
somedll!<lambda239>::operator()+0x102:
000007fe`8b048eb2 00488b add byte ptr [rax-75h],cl
000007fe`8b048eb5 084863 or byte ptr [rax+63h],cl
000007fe`8b048eb8 81d003000048 adc eax,48000003h
000007fe`8b048ebe 83f8ff cmp eax,0FFFFFFFFh
000007fe`8b048ec1 740a je somedll!<lambda239>::operator()+0x11d (000007fe`8b048ecd)
000007fe`8b048ec3 4889c2 mov rdx,rax
000007fe`8b048ec6 48899570080000 mov qword ptr [rbp+870h],rdx
000007fe`8b048ecd 486381e0030000 movsxd rax,dword ptr [rcx+3E0h]
0:019> u
somedll!<lambda239>::operator()+0x124:
000007fe`8b048ed4 483bd0 cmp rdx,rax
000007fe`8b048ed7 7501 jne somedll!<lambda239>::operator()+0x12a (000007fe`8b048eda)
000007fe`8b048ed9 cc int 3
000007fe`8b048eda 80b96303000000 cmp byte ptr [rcx+363h],0
000007fe`8b048ee1 7413 je somedll!<lambda239>::operator()+0x146 (000007fe`8b048ef6)
000007fe`8b048ee3 e8589b1000 call somedll!bla::bla::blabla::GetRNG (000007fe`8b152a40)
000007fe`8b048ee8 4889c1 mov rcx,rax
000007fe`8b048eeb 8b9570080000 mov edx,dword ptr [rbp+870h]
0:019> u
somedll!<lambda239>::operator()+0x141:
000007fe`8b048ef1 e8fa911000 call somedll!bla::bla::blabla::blabla::Seed (000007fe`8b1520f0)
000007fe`8b048ef6 4c8ba5b0080000 mov r12,qword ptr [rbp+8B0h]
000007fe`8b048efd 488d95f0070000 lea rdx,[rbp+7F0h]
000007fe`8b048f04 488d8dc0070000 lea rcx,[rbp+7C0h]
000007fe`8b048f0b 498b0424 mov rax,qword ptr [r12]
000007fe`8b048f0f 4c8da570080000 lea r12,[rbp+870h]
000007fe`8b048f16 488942d0 mov qword ptr [rdx-30h],rax
000007fe`8b048f1a 4c8962d8 mov qword ptr [rdx-28h],r12
the first instructions "add byte ptr" and "or byte ptr" at 000007fe`8b048eb2 don't make sense because rip-30 likely falls in the middle of an instruction, but after it seems to resync because it corresponds to the source code:
if (id == params.dbgbreak_id) {
__debugbreak();
}
if (params.derandomize) {
GetRNG().Seed(id);
}
000007fe`8b048ecd 486381e0030000 movsxd rax,dword ptr [rcx+3E0h]
000007fe`8b048ed4 483bd0 cmp rdx,rax // if (id == params.dbgbreak_id) {
000007fe`8b048ed7 7501 jne somedll!<lambda239>::operator()+0x12a (000007fe`8b048eda)
000007fe`8b048ed9 cc int 3 // __debugbreak(); }
000007fe`8b048eda 80b96303000000 cmp byte ptr [rcx+363h],0 // if (params.derandomize)
000007fe`8b048ee1 7413 je somedll!<lambda239>::operator()+0x146 (000007fe`8b048ef6)
000007fe`8b048ee3 e8589b1000 call somedll!bla::bla::blabla::GetRNG (000007fe`8b152a40)
000007fe`8b048ee8 4889c1 mov rcx,rax
000007fe`8b048eeb 8b9570080000 mov edx,dword ptr [rbp+870h]
000007fe`8b048ef1 e8fa911000 call somedll!bla::bla::blabla::blabla::Seed (000007fe`8b1520f0)
clearly there is no instruction begining at 000007fe8b048ee2 !
There is je at 000007fe8b048ee1, and call at 000007fe8b048ee3
So... I thought, hmmm there's a bug in the debugger... let's check the registers:
0:019> r
rax=ffffffffffffffff rbx=000000000021d420 rcx=000000000021d5d0
rdx=0000000002696568 rsi=0000000000005d38 rdi=0000000056eefc40
rip=000007fe8b048ee2 rsp=0000000056eef5b0 rbp=0000000056eef5e0
r8=0000000000000006 r9=000000000021d0b8 r10=0000000006456570
r11=0000000000000006 r12=0000000056eefe50 r13=00000000069a8820
r14=000000000021d1a8 r15=0000000056eefe60
iopl=0 nv up ei pl zr na po nc
cs=0033 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000246
What?? rip=000007fe8b048ee2 ?? How is that possible?
It explains why the debugger is showing garbage: it is trying to dissassemble starting from rip, but rip points to the middle of an instruction.
But why is the reported rip wrong? Is the OS culprit?
Am I missing something?

Related

VariantClear releases VT_DISPATCH -vs- MSDN documentation

VS2015 C++ / Windows7 SP1
Considering the following code:
CComPtr<IFontDisp> m_pFont;
::OleCreateFontIndirect(&fdesc,IID_IFontDisp,(void**)&m_pFont);
VARIANT var = m_pFont; // PSEUDO CODE
after this,
var.vt = 9; //VT_DISPATCH
var.DISPATCH = "oleaut32.dll/IFontDisp"
So all looks fine.
Now I call
::VariantClear(var);
And I debug into (ASM), I found this:
74CB2EA6 nop
CFont::Release:
--> 74CB2EA7 sub dword ptr [esp+4],4
74CB2EAC jmp CFont::Release (74CB2E79h)
74CB2EAE nop
74CB2EAF nop
74CB2EB0 nop
Following the code:
CFont::Release:
--> 74CB2E79 mov edi,edi
74CB2E7B push ebp
74CB2E7C mov ebp,esp
74CB2E7E push esi
74CB2E7F mov esi,dword ptr [ebp+8]
74CB2E82 push edi
74CB2E83 lea eax,[esi+0A8h]
74CB2E89 push eax
74CB2E8A call dword ptr [__imp__InterlockedDecrement#4 (74C91298h)]
74CB2E90 mov edi,eax
74CB2E92 test edi,edi
74CB2E94 je CFont::Release+261h (74CB30DAh)
74CB2E9A mov eax,edi
74CB2E9C pop edi
74CB2E9D pop esi
74CB2E9E pop ebp
74CB2E9F ret 4
So as I see, it releases the COM interface.
But if I see MSDN doc about VariantClear:
if the variant to be cleared is a COM object that is passed by
reference, the vtfield of the pvargparameter is VT_DISPATCH | VT_BYREF
or VT_UNKNOWN | VT_BYREF. In this case, VariantClear does not release
the object. Because the variant being cleared is a pointer to a
reference to an object, VariantClear has no way to determine if it is
necessary to release the object. It is therefore the responsibility of
the caller to release the object or not, as appropriate.
According to this, it should not call release on the IFontDisp.
Can anybody explain what is going on here?
Thanks.

Why is GDB filling the 0s of a memory address with 5s during a register info?

I am using GDB on a x64 CPU. As you can see, I am trying to access the value of the rip register and for some reason the address of the instruction the register is pointing to is displayed using 5s instead of 0s as it should be.
Dump of assembler code for function main:
0x0000000000001139 <+0>: push rbp
0x000000000000113a <+1>: mov rbp,rsp
0x000000000000113d <+4>: sub rsp,0x10
0x0000000000001141 <+8>: mov DWORD PTR [rbp-0x4],0x0
0x0000000000001148 <+15>: mov DWORD PTR [rbp-0x4],0x0
0x000000000000114f <+22>: jmp 0x1161 <main+40>
0x0000000000001151 <+24>: lea rdi,[rip+0xeac] # 0x2004
0x0000000000001158 <+31>: call 0x1030 <puts#plt>
0x000000000000115d <+36>: add DWORD PTR [rbp-0x4],0x1
0x0000000000001161 <+40>: cmp DWORD PTR [rbp-0x4],0x9
0x0000000000001165 <+44>: jle 0x1151 <main+24>
0x0000000000001167 <+46>: mov eax,0x0
0x000000000000116c <+51>: leave
0x000000000000116d <+52>: ret
End of assembler dump.
(gdb) break main
Breakpoint 1 at 0x1141: file Desktop/myprogram.c, line 6.
(gdb) run
Starting program: /home/william/Desktop/a.out
Breakpoint 1, main () at Desktop/myprogram.c:6
6 int i = 0;
(gdb) info register rip
rip 0x555555555141 0x555555555141 <main+8>
As you can see, the rip register contains the address of the mov instruction listed above but for some reason has replaced all the 0s for 5s. Any idea why?
Before running a position-independent executable, there is no base address so gcc assumes 0. This matches what you'll see from objdump -drwC -Mintel /bin/ls or whatever.
On running the executable to create a process, the OS's program-loader maps it to an address. x86-64 Linux chooses a page address that starts with 0x0000555555555... when GDB disables ASLR.
If you run it outside GDB, or with set disable-randomization off, then the address will still start with 0x000055555, but be randomized in some range.

Where is relocation data stored in a PE file if not in the .reloc section?

I have the following program:
BITS 32
section .data
_num1: dd 5
section .text
global _start
_start:
push ebp
mov ebp, esp
mov eax, 9
add eax, [_num2]
sub eax, [_num1]
leave
ret
_num2: dd 7
Which assembles into the x86 instructions below:
0x00401000 <+0>: push ebp
0x00401001 <+1>: mov ebp,esp
0x00401003 <+3>: mov eax,0x9
0x00401008 <+8>: add eax,DWORD PTR ds:0x401016
0x0040100e <+14>: sub eax,DWORD PTR ds:0x402000
0x00401014 <+20>: leave
0x00401015 <+21>: ret
Now, the addresses of the sub and add instructions seems pretty fixed (absolute). Indeed, the VirtualAddress of the .data section is 0x2000, but what if the program doesn't load at its preferred address and relocation must be applied?
In this case, since the VirtualAddress's are RVA's, the sections remain relative to each other, but the addresses above are fixed.
How does the loader know that it must change these addresses to point to the proper data items?

x86 asm - 12 bytes subtracted from esp. Only 8 needed

I've compiled this code with gcc (gcc -ggdb -mpreferred-stack-boundary=2 -o demo demo.c) and decompiled it to look at the assembly (I know it's using unsafe functions, this was for an exercise into buffer overflows):
#include<stdio.h>
CanNeverExecute()
{
printf("I can never execute\n");
exit(0);
}
GetInput()
{
char buffer[8];
gets(buffer);
puts(buffer);
}
main()
{
GetInput();
return 0;
}
Here is the assembly for the GetInput() Function:
(gdb) disas GetInput
Dump of assembler code for function GetInput:
0x08048432 <+0>: push ebp
0x08048433 <+1>: mov ebp,esp
0x08048435 <+3>: sub esp,0xc
=> 0x08048438 <+6>: lea eax,[ebp-0x8]
0x0804843b <+9>: mov DWORD PTR [esp],eax
0x0804843e <+12>: call 0x8048320 <gets#plt>
0x08048443 <+17>: lea eax,[ebp-0x8]
0x08048446 <+20>: mov DWORD PTR [esp],eax
0x08048449 <+23>: call 0x8048340 <puts#plt>
0x0804844e <+28>: leave
0x0804844f <+29>: ret
End of assembler dump.
Here is the assembly for the Main() Function:
(gdb) disas main
Dump of assembler code for function main:
0x08048450 <+0>: push ebp
0x08048451 <+1>: mov ebp,esp
0x08048453 <+3>: call 0x8048432 <GetInput>
0x08048458 <+8>: mov eax,0x0
0x0804845d <+13>: pop ebp
0x0804845e <+14>: ret
End of assembler dump.
I've set a breakpoint at line 13 (gets(buffer))
From Main(), I can see that the ebp value is pushed onto the stack. Then when GetInput() function is called the ret address is also pushed onto the stack. Once entered the GetInput function, the ebp value is pushed onto the stack again.
Now this is where I get confused:
0x08048435 <+3>: sub esp,0xc
The buffer variable is only 8 bytes, so 8 bytes should be subtracted from esp to allow for the buffer local variable.
The stack:
(gdb) x/8xw $esp
0xbffff404: 0x08048360 0x0804847b 0x002c3ff4 0xbffff418
0xbffff414: 0x08048458 0xbffff498 0x00147d36 0x00000001
(gdb) x/x &buffer
0xbffff408: 0x0804847b
0x08048458 is the ret address, 0xbffff418 is the old value of ebp, and 4 bytes of the buffer variable is in 0x0804847b, so I guess the other 4 bytes is 0x002c3ff4. But there seems to be another 4 bytes on the stack.
So my question is, why is it subtracting 12 bytes if only 8 bytes is needed? What's the extra 4 bytes for?
Thank you
It's because of the
mov DWORD PTR [esp],eax
Apparently, your puts and gets implementations require the argument to be pushed onto the stack.
Value [ebp-0xc] is actually [esp] now, that's why that dword is reserved ahead.
Why is it so? Doing it this way is more efficient, as you don't have to pop and push, but just move eax on [esp], so you spare at least one instruction. However, I guess this code has gone through some optimiation, because this one is clever.

Windbg _imp__xxx symbol's address seems to be dereferenced using the data segment register

I am learning Windbg. And for practice, I am debugging a 64bit fre app that create a process.
I added a breakpoint on CreateProcess (bp KERNEL32!CreateProcessWStub)
When the breakpoint is hit, I disassemble the code (u) and it looks like this:
Breakpoint 0 hit
KERNEL32!CreateProcessWStub:
000007f9`f8024ab4 4c8bdc mov r11,rsp
0:000> u #rip L20
KERNEL32!CreateProcessWStub:
000007f9`f8024ab4 4c8bdc mov r11,rsp
000007f9`f8024ab7 4883ec58 sub rsp,58h
000007f9`f8024abb 488b8424a8000000 mov rax,qword ptr [rsp+0A8h]
000007f9`f8024ac3 498943f0 mov qword ptr [r11-10h],rax
000007f9`f8024ac7 488b8424a0000000 mov rax,qword ptr [rsp+0A0h]
000007f9`f8024acf 498943e8 mov qword ptr [r11-18h],rax
000007f9`f8024ad3 488b842498000000 mov rax,qword ptr [rsp+98h]
000007f9`f8024adb 498943e0 mov qword ptr [r11-20h],rax
000007f9`f8024adf 488b842490000000 mov rax,qword ptr [rsp+90h]
000007f9`f8024ae7 498943d8 mov qword ptr [r11-28h],rax
000007f9`f8024aeb 8b842488000000 mov eax,dword ptr [rsp+88h]
000007f9`f8024af2 89442428 mov dword ptr [rsp+28h],eax
000007f9`f8024af6 8b842480000000 mov eax,dword ptr [rsp+80h]
000007f9`f8024afd 89442420 mov dword ptr [rsp+20h],eax
000007f9`f8024b01 ff1591951100 call qword ptr [KERNEL32!_imp_CreateProcessW (000007f9`f813e098)]
000007f9`f8024b07 4883c458 add rsp,58h
That call to _imp_CreateProcessW is misleading because when I trace (t) to the point where I am right at that call, that's is what I see
KERNEL32!CreateProcessWStub+0x4d:
000007f9`f8024b01 ff1591951100 call qword ptr [KERNEL32!_imp_CreateProcessW (000007f9`f813e098)] ds:000007f9`f813e098={KERNELBASE!CreateProcessW (000007f9`f7578960)}
So it looks like _imp_CreateProcessW address is a relative address (left by the linker?).
And that the data segment register (ds) is used somehow to resolve the final address (in this case, KERNELBASE!CreateProcessW (000007f9`f7578960))
This doesn't make sense though because I read that segments are not used in modern architecture (except for the fs and gs register that hold TCB's address)
My questions are:
what's going on there?
why is CreateProcessW not present in kernel32.dll (only the stub is). MSDN say that CreateProcess is in kernel32.dll
what's the story behind symbols that start with imp. Are they linker artifacts?
Thanks!!!
Note: I run .symfix and .reload at the beginning.
The value of the registers at that moment (right before the call):
0:000> r
rax=0000000000000000 rbx=0000000000000048 rcx=0000000000000000
rdx=0000000000535138 rsi=0000000000000000 rdi=0000000000000000
rip=000007f9f8024b01 rsp=00000000004df550 rbp=0000000000000000
r8=0000000000000000 r9=0000000000000000 r10=0000000000000000
r11=00000000004df5a8 r12=0000000000000000 r13=000007f7abfb1258
r14=0000000000000000 r15=0000000000000000
iopl=0 nv up ei pl nz na po nc
cs=0033 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000206
IIRC __imp_ and stubs were introduced to take care of SxS. You will notice that most if not all kernel32 & kernelbase calls end up calling __imp_.
If regards to stubs, a quick example is
IsDebuggerPresent()
Doing a GetProcAddress on this will return the address of IsDebuggerPresentStub which will jump to IsDebuggerPresent, which in turn will jump to:
_imp__IsDebuggerPresent
In essence, you're correct. The _imp__XXX works a bit like a VFT.

Resources