What is between ESP and EBP? - debugging

Right, I'm sure this is implicitly answered many times, but I seem not to be able to quite get to it.
If you have a (x86) stack trace (say, looking at it in WinDbg), and you look at the registers, what does it mean for EBP and ESP values to be x bytes apart?
Links:
https://stackoverflow.com/a/3699916/321013
https://stackoverflow.com/a/2466587/321013
https://stackoverflow.com/a/5738940/321013
To give an example of a recent stack trace I had:
0:016> k
ChildEBP RetAddr
1ac5ee8c 76b831bb ntdll!NtDelayExecution+0x15
1ac5eef4 76b83a8b KERNELBASE!SleepEx+0x65
1ac5ef04 0060e848 KERNELBASE!Sleep+0xf
1ac5ef10 76859d77 MyApp!application_crash::CommonUnhandledExceptionFilter+0x48 [...\applicationcrash.inc.cpp # 47]
1ac5ef98 775a0df7 kernel32!UnhandledExceptionFilter+0x127
1ac5efa0 775a0cd4 ntdll!__RtlUserThreadStart+0x62
1ac5efb4 775a0b71 ntdll!_EH4_CallFilterFunc+0x12
1ac5efdc 77576ac9 ntdll!_except_handler4+0x8e
1ac5f000 77576a9b ntdll!ExecuteHandler2+0x26
1ac5f0b0 7754010f ntdll!ExecuteHandler+0x24
1ac5f0b0 6e8858bb ntdll!KiUserExceptionDispatcher+0xf
1ac5f400 74e68ed7 mfc80u!ATL::CSimpleStringT<wchar_t,1>::GetString [f:\dd\vctools\vc7libs\ship\atlmfc\include\atlsimpstr.h # 548]
1ac5fec0 6e8c818e msvcr80!_NLG_Return [F:\dd\vctools\crt_bld\SELF_X86\crt\prebuild\eh\i386\lowhelpr.asm # 73]
1ac5ff48 74e429bb mfc80u!_AfxThreadEntry+0xf2 [f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\thrdcore.cpp # 109]
1ac5ff80 74e42a47 msvcr80!_callthreadstartex+0x1b [f:\dd\vctools\crt_bld\self_x86\crt\src\threadex.c # 348]
1ac5ff88 76833677 msvcr80!_threadstartex+0x66 [f:\dd\vctools\crt_bld\self_x86\crt\src\threadex.c # 326]
1ac5ff94 77569f02 kernel32!BaseThreadInitThunk+0xe
1ac5ffd4 77569ed5 ntdll!__RtlUserThreadStart+0x70
1ac5ffec 00000000 ntdll!_RtlUserThreadStart+0x1b
0:016> r
eax=00000000 ebx=1ac5efc8 ecx=19850614 edx=00000000 esi=1ac5eed0 edi=00000000
eip=7754fd21 esp=1ac5ee8c ebp=1ac5eef4 iopl=0 nv up ei pl nz na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010206
Values of ESP 1ac5ee8c - EBP 1ac5eef4 = 104 bytes difference. So what's in there?

ESP is the current stack pointer. EBP is the base pointer for the current stack frame.
When you call a function, typically space is reserved on the stack for local variables. This space is usually referenced via EBP (all local variables and function parameters are a known constant offset from this register for the duration of the function call.) ESP, on the other hand, will change during the function call as other functions are called, or as temporary stack space is used for partial operation results.
Note that most compilers these days have an option to reference all local variables through ESP. This frees up EBP for use as a general purpose register.
In general, when you look at the disassembly code at the top of a function you'll see something like this:
push EBP
mov EBP, ESP
sub ESP, <some_number>
So EBP will point to the top of your stack for this frame, and ESP will point to the next available byte on the stack. (Stacks usually - but don't have to - grow down in memory.)

Usually, this space is reserved for local variables that end up stored on the stack. At the start of the function, ESP is decremented by the appropriate value.
In your case, there are 104 bytes worth of locals in the function.

Related

Assembly debugging issue

So I have the assembly code below and the goal is to run the code without hitting the explode bomb call. The user enters 6 numbers with spaces in between but that part isn't too important as it is mostly handled by the read six numbers function which is known to be good and not explode the bomb.
0x0000000000400f0c <+0>: push %rbp
0x0000000000400f0d <+1>: push %rbx
0x0000000000400f0e <+2>: sub $0x28,%rsp
0x0000000000400f12 <+6>: mov %rsp,%rsi
0x0000000000400f15 <+9>: callq 0x4015da <read_six_numbers>
0x0000000000400f1a <+14>: cmpl $0x0,(%rsp)
0x0000000000400f1e <+18>: jne 0x400f27 <phase_2+27>
0x0000000000400f20 <+20>: cmpl $0x1,0x4(%rsp)
0x0000000000400f25 <+25>: je 0x400f48 <phase_2+60>
0x0000000000400f27 <+27>: callq 0x4015a4 <explode_bomb>
0x0000000000400f2c <+32>: jmp 0x400f48 <phase_2+60>
0x0000000000400f2e <+34>: mov -0x8(%rbx),%eax
0x0000000000400f31 <+37>: add -0x4(%rbx),%eax
0x0000000000400f34 <+40>: cmp %eax,(%rbx)
0x0000000000400f36 <+42>: je 0x400f3d <phase_2+49>
0x0000000000400f38 <+44>: callq 0x4015a4 <explode_bomb>
0x0000000000400f3d <+49>: add $0x4,%rbx
0x0000000000400f41 <+53>: cmp %rbp,%rbx
0x0000000000400f44 <+56>: jne 0x400f2e <phase_2+34>
0x0000000000400f46 <+58>: jmp 0x400f54 <phase_2+72>
0x0000000000400f48 <+60>: lea 0x8(%rsp),%rbx
0x0000000000400f4d <+65>: lea 0x18(%rsp),%rbp
0x0000000000400f52 <+70>: jmp 0x400f2e <phase_2+34>
0x0000000000400f54 <+72>: add $0x28,%rsp
0x0000000000400f58 <+76>: pop %rbx
0x0000000000400f59 <+77>: pop %rbp
0x0000000000400f5a <+78>: retq
I know that the read 6 numbers part works fine and doesnt set off the bomb. All it does is get the input.
Hey I'm not real good at assembly but I'm working on this and I think I've figured out the first number is 0 and the second is 1 but that could be wrong. I see the comparison on line +14 but im not sure if thats comparing the first value or just making sure that the string the user entered wasnt empty. I know you're supposed to put in 6 numbers and that's only the first 2 though. I'm a bit confused about what lines +34 to +40 do. I get that that's where the compared numbers change but I'm not sure how it affects them. If anyone is good with assembly and can help me out that would be awesome.

Dumping W32pServiceTable

I want to see what function in win32k.sys driver handles specific syscall number.
I attach windbg to GUI process since win32k.sys is season space driver.
Then I shift first DWORD value right by 4 bits add base address of W32pServiceTable and use u command to show function in WinDbg but address isn't valid. I checked KiSystemCall64 and it seems to be doing the same thing.
!process 0 0 winlogon.exe
.process /p (PROCESS addr)
.reload
Answer: DWORD value from table is loaded with this instruction
movsxd r11,dword ptr [r10+rax*4]
W32pServiceTable DWORD values has bit at 31 position set to 1 so movsxd sets upper 32 bits of r11 register to 1 then adding r11 and table base address leads to correct function.
These values are negative so you need to preserve that when you shift off the bits. For example:
0: kd> dd win32k!W32pServiceTable L1
fffff88b`d1568000 ff8c8340
0: kd> u win32k!W32pServiceTable + ffffffff`fff8c834 L1
win32k!NtUserGetThreadState:
fffff88b`d14f4834 4883ec28 sub rsp,28h
Also, WinDbg is very picky/weird/broken/unpredictable when it comes to sign extension so you need to be careful about how you do this. For example, this doesn't work:
0: kd> u win32k!W32pServiceTable + fff8c834 L1
fffff88c`d14f4834 ?? ???
Due to WinDbg zero extending the value. But this does:
0: kd> u win32k!W32pServiceTable + (fff8c834) L1
win32k!NtUserGetThreadState:
fffff88b`d14f4834 4883ec28 sub rsp,28h
Because the () causes WinDbg to sign extend instead of zero extend.
Lastly, this happens even on the normal service table, it's not just a Win32k thing.

Why am I getting an unexpected `0xcc` byte when loading nearby code bytes? Is it because of segment register %es?

I got some inconsistent result of instruction.
I don't know why this happens, so I suspect %es register is doing something weird, but I'm not sure.
Look at below code snippet.
08048400 <main>:
8048400: bf 10 84 04 08 mov $HERE,%edi
8048405: 26 8b 07 mov %es:(%edi),%eax # <----- Result 1
8048408: bf 00 84 04 08 mov $main,%edi
804840d: 26 8b 07 mov %es:(%edi),%eax # <----- Result 2
08048410 <HERE>:
8048410: 11 11 adc %edx,(%ecx)
8048412: 11 11 adc %edx,(%ecx)
Result 1:
%eax : 0x11111111
Seeing this result, I guessed that mov %es:(%edi),%eax to be something like mov (%edi),%eax.
Because 0x11111111 is stored at HERE.
Result 2:
%eax : 0x048410cc
However, the result of Result 2 was quite different.
I assumed %eax to be 0x048410bf, because this value is stored at main.
But the result was different as you can see.
Question:
Why this inconsistency of the result happens?
By the way, value of %es was always 0x7b during execution of both instruction.
es is a red herring. The difference you see is 1 byte at main, cc vs. bf. That is because you used a software breakpoint at main and your debugger inserted an int3 instruction which has machine code cc temporarily overwriting your actual code.
Do not set a breakpoint where you intend to read from, or use a hardware breakpoint instead which does not modify code.

Understanding disassembled binary from Objdump - What are the fields from the output

I get the following output when I disassembled a simple ARM binary file using the command "arm-linux-gnueabihf-objdump -d a.out"
00008480 <_start>:
8480: f04f 0b00 mov.w fp, #0
8484: f04f 0e00 mov.w lr, #0
8488: bc02 pop {r1}
848a: 466a mov r2, sp
What do different columns represent here? For example, 8480 and f04f 0b00 (from the 2nd line of code)
The first column is the address of the code in memory. 0x8480 means the memory address of this piece of code is 0x8480.
The second column is the hex representation of the code. f04f 0b00 means from memory address 0x8480(included) to 0x8484(excluded), there are 4 bytes of code, f0, 4f, 0b, 00.
The remaining is the disassembled code. They are disassembled from the code in second column.

power8 assembly code with shared build issue with save and restore of TOC

I have the following assembly code
.machine power8
.abiversion 2
.section ".toc","aw"
.section .text
GLOBAL(myfunc)
myfunc:
stdu 1,-240(1)
mflr 0
std 0, 0*8(1)
mfcr 8
std 8, 1*8(1)
std 2, 2*8(1)
# Save all non-volatile registers R14-R31
std 14, 4*8(1)
...
# Save all the non-volatile FPRs
...
stwu 1, -48(1)
bl function_call
nop
addi 1, 1, 48
ld 0, 0*8(1)
mtlr 0
ld 8, 1*8(1)
ld 2, 2*8(1)
...
# epilogue, restore stack frame
This works fine with static build but shared build gives segmentation fault in
00000157.plt_call.__tls_get_addr_opt##GLIBC_2.22, should the shared build be handled differently in power8 w.r.t TOC?
The calling convention is the same between POWER 8 and previous processors. However, there has been changes with regards to the TOC pointer (r2) handling between ABIv1 and ABIv2.
In ABIv2, the caller does not establish the TOC pointer in r2; the called function should do this for global entry points (ie, where the TOC pointer may not be the same as that used in the callee). To do this, ABIv2 functions will have a prologue that sets r2:
0000000000000000 <foo>:
0: 00 00 4c 3c addis r2,r12,0
4: 00 00 42 38 addi r2,r2,0
- this depends on r12 containing the address of the function's global entry point (those 0 values will be replaced with actual offsets at final link time).
I don't see any code setting r12 appropriately in your example. Are you sure you're complying with the v2 ABI there?
The ABIv2 spec is available here: https://members.openpowerfoundation.org/document/dl/576 Section 2.3.2 will be the most relevant for this issue.

Resources