So, I see this line in one of the callstacks of a dump (x86/Windows 7) I am looking at. I have heavily snipped it as my question is pertaining only to this call.
Args to Child
01111111 04444444 05555555 ntdll!KiUserExceptionDispatcher+0xf
and going by: http://www.nynaeve.net/Code/KiUserExceptionDispatcher.c
It looks like the first two arguments on the stack must be the context record and the exception record. However with some experimentation I noted that 01111111 is not the first argument. It actually starts from 04444444. So, in this case .cxr 04444444 and .exr 05555555 display sane output.
Now, I understand the debugger might just show whatever is on the stack at that point and I shouldn't probably rely on that alone but if everything below that line is marked with "stack unwind information not available. Following frames may be wrong", how am I to know that I should ignore 01111111?
UPDATE
Lets try a different approach. Here are 2 relevant pieces of information:
Args to Child
0ccccccc 77895ac4 00000000 kernel32!UnhandledExceptionFilter+0x9e
[... various other calls here, leading up to ...]
0eeeeeee 0aaaaaaa 0bbbbbbb ntdll!KiUserExceptionDispatcher+0xf
So, check this out. The lone parameter to UnhandledExceptionFilter is an EXCEPTION_POINTERS* structure, right?
0:010> dd 0ccccccc l2
0ddddddd 0bbbbbbb 0aaaaaaa
In the EXCEPTION_POINTERS struct, the first field is the EXCEPTION_RECORD (0bbbbbbb) while the second is the CONTEXT_RECORD (0aaaaaaa). However in the call to KiUserEceptionDispatcher, these arguments appear in the opposite way. Not to mention the fact 0eeeeeee is NOT the first parameter to KiUserExceptionDispatcher but 0ccccccc IS the first parameter to UnhandledExceptionFilter.
I am SO confused!
windows 7 x86 32 bit machine
winkey + r -> windbg calc
bp ntdll!KiUserExceptionDispatcher
f5
divide 0/0 in calculator to raise an exception
(ac8.c8c): C++ EH exception - code e06d7363 (first chance)
Breakpoint 0 hit
eax=0023e1ec ebx=02b12fd0 ecx=00000003 edx=00000000 esi=02b13178 edi=00000001
eip=76e77048 esp=0023dee0 ebp=0023e23c iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
ntdll!KiUserExceptionDispatcher:
76e77048 fc cld
your post shows the return address to be + 0xf so lets see whats upto that point
0:000> u . .+f
ntdll!KiUserExceptionDispatcher:
76e77048 fc cld
76e77049 8b4c2404 mov ecx,dword ptr [esp+4]
76e7704d 8b1c24 mov ebx,dword ptr [esp]
76e77050 51 push ecx
76e77051 53 push ebx
76e77052 e85d88fdff call ntdll!RtlDispatchException (76e4f8b4)
76e77057 0ac0 or al,al
so it appears you have broken after entering RtlDispatchException from your call stack
breaking to enter the call
0:000> tc
eax=0023e1ec ebx=0023dee8 ecx=0023df08 edx=00000000 esi=02b13178 edi=00000001
eip=76e77052 esp=0023ded8 ebp=0023e23c iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
ntdll!KiUserExceptionDispatcher+0xa:
76e77052 e85d88fdff call ntdll!RtlDispatchException (76e4f8b4)
0:000> t
eax=0023e1ec ebx=0023dee8 ecx=0023df08 edx=00000000 esi=02b13178 edi=00000001
eip=76e4f8b4 esp=0023ded4 ebp=0023e23c iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
ntdll!RtlDispatchException:
76e4f8b4 8bff mov edi,edi
looking at stack if you ask windbg to be verbose it will even decipher the context for you
0:000> kb 3
# ChildEBP RetAddr Args to Child
00 0023ded0 76e77057 0023dee8 0023df08 0023dee8 ntdll!RtlDispatchException
01 0023ded0 7521b760 0023dee8 0023df08 0023dee8 ntdll!KiUserExceptionDispatcher+0xf
02 0023e23c 7579359c e06d7363 00000001 00000003 KERNELBASE!RaiseException+0x58
0:000> kv 3
# ChildEBP RetAddr Args to Child
00 0023ded0 76e77057 0023dee8 0023df08 0023dee8 ntdll!RtlDispatchException (FPO: [Non-Fpo])
01 0023ded0 7521b760 0023dee8 0023df08 0023dee8 ntdll!KiUserExceptionDispatcher+0xf (FPO: [2,0,0]) (CONTEXT # 0023df08)
02 0023e23c 7579359c e06d7363 00000001 00000003 KERNELBASE!RaiseException+0x58 (FPO: [Non-Fpo])
exr output
0:000> .exr poi(#esp+4)
ExceptionAddress: 7521b760 (KERNELBASE!RaiseException+0x00000058)
ExceptionCode: e06d7363 (C++ EH exception)
ExceptionFlags: 00000001
NumberParameters: 3
Parameter[0]: 19930520
Parameter[1]: 0023e294
Parameter[2]: 007c15b4
unable to find C-Runtime symbols, even with unqualified search
context record output
0:000> dt ntdll!_CONTEXT poi(#esp+8)
+0x000 ContextFlags : 0x1003f
+0x004 Dr0 : 0
+0x008 Dr1 : 0
+0x00c Dr2 : 0
+0x010 Dr3 : 0
+0x014 Dr6 : 0
+0x018 Dr7 : 0
+0x01c FloatSave : _FLOATING_SAVE_AREA
+0x08c SegGs : 0
+0x090 SegFs : 0x3b
+0x094 SegEs : 0x23
+0x098 SegDs : 0x23
+0x09c Edi : 1
+0x0a0 Esi : 0x2b13178
+0x0a4 Ebx : 0x2b12fd0
+0x0a8 Edx : 0
+0x0ac Ecx : 3
+0x0b0 Eax : 0x23e1ec
+0x0b4 Ebp : 0x23e23c
+0x0b8 Eip : 0x7521b760
+0x0bc SegCs : 0x1b
+0x0c0 EFlags : 0x202
+0x0c4 Esp : 0x23e1ec
+0x0c8 SegSs : 0x23
+0x0cc ExtendedRegisters : [512] "???"
you can even get both by use .extptr (note you may need to reset context to default scope using .cxr after using this command)
0:000> .exptr (#esp+4)
----- Exception record at 0023dee8:
ExceptionAddress: 7521b760 (KERNELBASE!RaiseException+0x00000058)
ExceptionCode: e06d7363 (C++ EH exception)
ExceptionFlags: 00000001
NumberParameters: 3
Parameter[0]: 19930520
Parameter[1]: 0023e294
Parameter[2]: 007c15b4
unable to find C-Runtime symbols, even with unqualified search
----- Context record at 0023df08:
eax=0023e1ec ebx=02b12fd0 ecx=00000003 edx=00000000 esi=02b13178 edi=00000001
eip=7521b760 esp=0023e1ec ebp=0023e23c iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
KERNELBASE!RaiseException+0x58:
7521b760 c9 leave
0:000> kb 3
# ChildEBP RetAddr Args to Child
00 0023e23c 7579359c e06d7363 00000001 00000003 KERNELBASE!RaiseException+0x58
01 0023e274 0079eee0 0023e294 007c15b4 02b13178 msvcrt!_CxxThrowException+0x48
02 0023e288 0079146e 02b13178 80000002 c87a3f02 calc!divrat+0x69
0:000> .cxr
Resetting default scope
0:000> kb 3
# ChildEBP RetAddr Args to Child
00 0023ded0 76e77057 0023dee8 0023df08 0023dee8 ntdll!RtlDispatchException
01 0023ded0 7521b760 0023dee8 0023df08 0023dee8 ntdll!KiUserExceptionDispatcher+0xf
02 0023e23c 7579359c e06d7363 00000001 00000003 KERNELBASE!RaiseException+0x58
hope this suffices to research on your own for your specific situation for which you cant divulge the actual windbg stack trace
Related
I’ve got a shellcode. It opens calculator in my buffer overflow program.
0: eb 16 jmp 0x18
2: 5b pop ebx
3: 31 c0 xor eax,eax
5: 50 push eax
6: 53 push ebx
7: bb 4d 11 86 7c mov ebx,0x7c86114d
c: ff d3 call ebx
e: 31 c0 xor eax,eax
10: 50 push eax
11: bb ea cd 81 7c mov ebx,0x7c81cdea
16: ff d3 call ebx
18: e8 e5 ff ff ff call 0x2
1d: 63 61 6c arpl WORD PTR [ecx+0x6c],sp
20: 63 2e arpl WORD PTR [esi],bp
22: 65 78 65 gs js 0x8a
25: 00 90 90 90 90 90 add BYTE PTR [eax-0x6f6f6f70],dl
2b: 90 nop
2c: 90 nop
2d: 90 nop
2e: 90 nop
2f: 90 nop
Apart from the main question being “What does this shellcode do line by line”, I am particularly interested in:
The jmp operation, why and where does my program jump?
The arpl stuff, I see it for the first time and google does not help me much... Same with GS operation
The jmp 0x18 is a relative jump to offset 0x18, which is practically the end of your code. It then calls address 0x2 (again, relative). This call places the "return address" on the stack, so it could be popped from it, giving you a clue about the address in which this relative shellcode is being executed. And indeed, the pop ebx at offset 0x2 is getting the address from the stack.
I said that 0x18 is the end of the code, because the lines after it are data bytes and not asm opcodes. This is why you see arpl. If you look at the hex values of the bytes, you will see:
calc.exe\0 ==> 0x63 0x61 0x63 0x6c 0x2e 0x65 0x78 0x65 0x00
Edited:
The full flow of the shellcode is:
jmp 0x18 - jump to to the last code instruction of the shellcode
call 0x2 - returns to offset 2, and stores the address of offset 0x1D on the stack
pop ebx - ebx := address from the stack, which is the address of the string "calc.exe"
xor eax,eax - common opcode to zero the register: eax := 0
push eax - push the value 0 as the second argument for a future function call
push ebx - push the pointer to "calc.exe" as the first argument for a future function call
mov ebx,0x7c86114d - ebx will be a fixed address (probably WinExec)
call ebx - call the function: WinExec("calc.exe", 0)
xor eax,eax - again, eax := 0
push eax - push the value 0 as the first argument for a future function call
mov ebx,0x7c81cdea - ebx will be a fixed address (probably exit)
call ebx - call the function: exit(0)
I'm working on a port of some software with inline assembly because we took a few bug reports from a Debian maintainer under X32. The code is fine under both X86 and X64.
We're catching a bus error on the emms instruction:
...
0x005520fd <+3885>: pop %rsp
0x005520fe <+3886>: emms
=> 0x00552100 <+3888>: pop %rbx
0x00552101 <+3889>: jmpq 0x5519e3
0x00552106 <+3894>: nopw %cs:0x0(%rax,%rax,1)
...
According to the manual, the following exceptions are raised:
Exceptions:
RM PM VM SMM Description
#UD #UD #UD #UD If CR0.EM = 1
#NM #NM #NM #NM If CR0.TS = 1
#MF #MF #MF #MF If pending FPU Exception
Here is the mask used in the MMX status register:
mxcsr 0x1f80 [ IM DM ZM OM UM PM ]
I don't believe I have access to the control registers to determine what actually caused the exception, so I'm having trouble locating the cause of the bus error.
What are some of the potential causes of the bus error? Or how can I trouble shoot this further?
Here's info float:
(gdb) info float
R7: Empty 0xffffffffffffffffffff
R6: Empty 0xffffa5a5a5a5a5a5a5a5
R5: Empty 0xfffffedcba9876543210
R4: Empty 0xffffb182db48cf349120
R3: Empty 0xffff926cd0b6a839b535
R2: Empty 0xfffff373de2d49584e7a
R1: Empty 0xffff16166e76b1bb925f
=>R0: Empty 0xffff24f0130c63ac9332
Status Word: 0x0000
TOP: 0
Control Word: 0x037f IM DM ZM OM UM PM
PC: Extended Precision (64-bits)
RC: Round to nearest
Tag Word: 0xffff
Instruction Pointer: 0x00:0x00000000
Operand Pointer: 0x00:0x00000000
Opcode: 0x0000
And here's from info registers:
(gdb) info registers
rax 0xffffcb58 0xffffcb58
rbx 0x30 0x30
rcx 0x14f3 0x14f3
rdx 0x61d560 0x61d560
rsi 0xffffcb08 0xffffcb08
rdi 0x14 0x14
rbp 0xffffcb58 0xffffcb58
rsp 0xb62f7cbfffffc8d8 0xb62f7cbfffffc8d8
r8 0x0 0x0
r9 0x40 0x40
r10 0x2e676e696e6e7572 0x2e676e696e6e7572
r11 0x246 0x246
r12 0x9028a0 0x9028a0
r13 0xffffcaf0 0xffffcaf0
r14 0x8f6120 0x8f6120
r15 0xffffca6c 0xffffca6c
rip 0x552100 0x552100
eflags 0x10246 [ PF ZF IF RF ]
cs 0x33 0x33
ss 0x2b 0x2b
ds 0x2b 0x2b
es 0x2b 0x2b
fs 0x63 0x63
gs 0x0 0x0
Here's a breakout of the MMX status register bits:
IM - Invalid Operation Mask
DM - Denormalized Mask
ZM - Divide By Zero Mask
OM - Overflow Mask
UM - Underflow Mask
PM - Precision Mask
EMMS is executing without problem, as shown the arrow and the value of rip the fault is with the following pop because rsp points to invalid memory. The correct value of rsp is something less than 0x100000000.
Is there a way to setup a breakpoint on the interrupt service routine on Windows which is responsible to trigger thread scheduling and print the EIP of the thread which was interrupted?
I tried to with hal!HalpClockInterrupt but it seems its not the right place. nt!KeUpdateRunTime seams better:
Breakpoint 3 hit
nt!KeUpdateRunTime:
805410dc a11cf0dfff mov eax,dword ptr ds:[FFDFF01Ch]
kd> !thread
THREAD 82c23bf0 Cid 0320.0474 Teb: 7ffa2000 Win32Thread: 00000000 RUNNING on processor 0
Impersonation token: e1c1f990 (Level Impersonation)
Owning Process 0 Image: <Unknown>
Attached Process 82c2dca0 Image: svchost.exe
Wait Start TickCount 6298 Ticks: 14 (0:00:00:00.218)
Context Switch Count 64 IdealProcessor: 0
UserTime 00:00:00.453
KernelTime 00:00:04.312
Win32 Start Address 0x7730a5f7
Start Address 0x7c8106f9
Stack Init f4dc1000 Current f4dc0d34 Base f4dc1000 Limit f4dbe000 Call 0
Priority 8 BasePriority 8 PriorityDecrement 0 DecrementCount 0
ChildEBP RetAddr Args to Child
f4dc0d54 805410ae 00000000 000000d1 0197fb94 nt!KeUpdateRunTime (FPO: [1,1,0])
f4dc0d54 806d2c9e 00000000 000000d1 0197fb94 nt!KeUpdateSystemTime+0x13e (FPO: [0,2] TrapFrame # f4dc0cdc)
f4dc0d54 805410ae 00000000 000000d1 0197fb94 hal!HalEndSystemInterrupt+0x4e (FPO: [2,2,0])
f4dc0d54 77306f5f 00000000 000000d1 0197fb94 nt!KeUpdateSystemTime+0x13e (FPO: [0,2] TrapFrame # f4dc0d64)
WARNING: Frame IP not in any known module. Following frames may be wrong.
0197fb94 77308dc1 0197fbdc 025c1ec0 03478e70 0x77306f5f
0197fbbc 77309b4a 0197fbdc 00000000 00000001 0x77308dc1
0197ff18 7730a711 02560008 00000000 00000000 0x77309b4a
0197ffb4 7c80b729 00000000 00000000 00000000 0x7730a711
0197ffec 00000000 7730a5f7 00000000 00000000 0x7c80b729
Question still is open how to get EIP. Seems Windbg knows how to do it but I would like to understand how. It seems a _KTRAP_FRAME is at _KTHREAD->KernelStack - 4.
You are very close, but as the current running thread was interrupted by an interrupt, the KTRAP_FRAME (saved registers from the interrupted thread) are put on the stack at that time (when nt!KeUpdateSystemTime() is called).
(Note: live Kernel Debugging on Windows XP SP3 x86).
Reload hal symbols ; see BPs and go:
0: kd>.reload /f hal
0: kd> bl
0 e 805450d0 0001 (0001) nt!KeUpdateSystemTime
1 e 806e5e54 0001 (0001) hal!HalpClockInterrupt
0: kd> g
OK,BP hit at nt!KeUpdateSystemTime:
Breakpoint 0 hit
nt!KeUpdateSystemTime:
805450d0 b90000dfff mov ecx,0FFDF0000h
Let see the stack, include FPO and trap frames:
0: kd> kv
ChildEBP RetAddr Args to Child
afb47d64 004482ef badb0d00 01bbb9c4 00000000 nt!KeUpdateSystemTime (FPO: [0,2] TrapFrame # afb47d64)
WARNING: Stack unwind information not available. Following frames may be wrong.
01f9d814 004483f1 01bb0020 01bbb9c4 000006a2 gfsvc32+0x482ef
01f9d828 004488ef 02c108c0 00081000 000003e8 gfsvc32+0x483f1
01f9d890 0044dc92 000102ee 01f9fd8c 02c108c0 gfsvc32+0x488ef
01f9feac 00437c59 000102ee 00000c90 00000000 gfsvc32+0x4dc92
01f9ffb4 7c80b729 00c9cb40 01e9fffc 00000020 gfsvc32+0x37c59
01f9ffe0 7c80b72f 00000000 00000000 00000000 kernel32!BaseThreadStart+0x37 (FPO: [Non-Fpo])
01f9ffe4 00000000 00000000 00000000 004a6727 kernel32!BaseThreadStart+0x3d (FPO: [Non-Fpo])
Userland thread was interrupted, trap frame is at 0xafb47d64. Let's see the thread:
0: kd> !thread
THREAD 8a3702e8 Cid 0c90.0cf8 Teb: 7ffd5000 Win32Thread: e198a360 RUNNING on processor 0
Not impersonating
DeviceMap e1f236f0
Owning Process 0 Image: <Unknown>
Attached Process 89e7fda0 Image: testk.exe
Wait Start TickCount 21252 Ticks: 2 (0:00:00:00.031)
Context Switch Count 45160 IdealProcessor: 0 LargeStack
UserTime 00:00:18.281
KernelTime 00:00:20.125
Win32 Start Address 0x004a6727
Start Address kernel32!BaseThreadStartThunk (0x7c810729)
Stack Init afb48000 Current afb479c4 Base afb48000 Limit afb44000 Call 0
Priority 13 BasePriority 13 PriorityDecrement 0 DecrementCount 16
ChildEBP RetAddr Args to Child
afb47d64 004482ef badb0d00 01bbb9c4 00000000 nt!KeUpdateSystemTime (FPO: [0,2] TrapFrame # afb47d64)
WARNING: Stack unwind information not available. Following frames may be wrong.
01f9d814 004483f1 01bb0020 01bbb9c4 000006a2 gfsvc32+0x482ef
01f9d828 004488ef 02c108c0 00081000 000003e8 gfsvc32+0x483f1
01f9d890 0044dc92 000102ee 01f9fd8c 02c108c0 gfsvc32+0x488ef
01f9feac 00437c59 000102ee 00000c90 00000000 gfsvc32+0x4dc92
01f9ffb4 7c80b729 00c9cb40 01e9fffc 00000020 gfsvc32+0x37c59
01f9ffe0 7c80b72f 00000000 00000000 00000000 kernel32!BaseThreadStart+0x37 (FPO: [Non-Fpo])
01f9ffe4 00000000 00000000 00000000 004a6727 kernel32!BaseThreadStart+0x3d (FPO: [Non-Fpo])
So when the thread is interrupted, hal!HalpClockInterrupt() gets called (see !idt -a for the ISRs) and a trap frame is built. The trap frame pointer is currently in the ebp register:
0: kd> r #ebp
ebp=afb47d64
So, EBP = pointer to KTRAP_FRAME = 0xafb47d64
A trap frame is like a "context" structure as it keeps all registers from the interrupted thread. Let's see what is the offset of eip:
0: kd> dt nt!_ktrap_frame eip
+0x068 Eip : Uint4B
EIP is at offset 0x68 in the KTRAP_FRAME structure. Just apply the offset:
0: kd> dd #ebp+0x68 L1
afb47dcc 004482ef
The user-land thread was interrupted while at EIP = 0x4482ef. Let's confirm this using the '.trap' command (could have been '.trap afb47d64' rather than using #ebp):
0: kd> .trap #ebp
ErrCode = 00000000
eax=00002ba2 ebx=00c9cb40 ecx=01bb0020 edx=01bbb9c4 esi=00c9cb40 edi=01e9fffc
eip=004482ef esp=01f9d814 ebp=01f9d814 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=0030 gs=0000 efl=00000202
gfsvc32+0x482ef:
001b:004482ef eb07 jmp gfsvc32+0x482f8 (004482f8)
BTW, you can easily see how the trap frame is constructed in hal!HalpClockInterrupt() by disassembling it:
0: kd> u hal!HalpClockInterrupt L0n10
hal!HalpClockInterrupt:
806e5e54 54 push esp
806e5e55 55 push ebp
806e5e56 53 push ebx
806e5e57 56 push esi
806e5e58 57 push edi
806e5e59 83ec54 sub esp,54h
806e5e5c 8bec mov ebp,esp
806e5e5e 89442444 mov dword ptr [esp+44h],eax
806e5e62 894c2440 mov dword ptr [esp+40h],ecx
806e5e66 8954243c mov dword ptr [esp+3Ch],edx
See how offsets above correspond to the KTRAP_FRAME member offsets:
0: kd> dt nt!_ktrap_frame eax
+0x044 Eax : Uint4B
0: kd> dt nt!_ktrap_frame ecx
+0x040 Ecx : Uint4B
0: kd> dt nt!_ktrap_frame edx
+0x03c Edx : Uint4B
Hope it answers your question.
-- edit --
As my example was on Win XP SP3, you might have different function names on other Windows system.
Example on Win8.1 (x86). If you can't find the clock interrupt function name, I'd try to check the IDT first:
0: kd>idt -a
[...snip...]
6b2ac55a000000d1: 81a237c8 hal!HalpTimerClockInterrupt
6b2ac55a000000d2: 81a23aa4 hal!HalpTimerClockIpiRoutine
[...snip...]
Only two of the 256 vectors have "clock" in their names (notice that one is for IPI [Inter Processor Interrupt], the other one is the usual clock interrupt).
I'd go for hal!HalpTimerClockInterrupt, try to step into this function and see which functions are called later.
It happens you can break on nt!KiUpdateTime or nt!KiUpdateRunTime functions:
0: kd> !thread
THREAD 9d0af680 Cid 0bec.0bf0 Teb: 7f8ae000 Win32Thread: 9ce51470 RUNNING on processor 0
Not impersonating
DeviceMap a0971118
Owning Process 9d161c40 Image: calc.exe
Attached Process N/A Image: N/A
Wait Start TickCount 63249 Ticks: 3 (0:00:00:00.046)
Context Switch Count 66956 IdealProcessor: 0
UserTime 00:01:12.609
KernelTime 00:00:01.281
Win32 Start Address calc!WinMainCRTStartup (0x003db8d4)
Stack Init ac49bfe0 Current ac49be04 Base ac49c000 Limit ac499000 Call 0
Priority 10 BasePriority 8 UnusualBoost 0 ForegroundBoost 2 IoPriority 2 PagePriority 5
ChildEBP RetAddr Args to Child
ac49bcf4 81ad2ef6 81c63c50 00000002 00000000 nt!KiUpdateRunTime (FPO: [Non-Fpo])
ac49bd40 81bdf7a7 ac49be38 ffd0fc98 00000002 nt!KiUpdateTime+0x23c (FPO: [Non-Fpo])
ac49bd90 81a134ae 81a10858 ffffffff ac49beb8 nt!KeClockInterruptNotify+0x67 (FPO: [0,15,4])
ac49bda0 81a23993 00000002 000000d1 00000000 hal!HalpTimerClockInterruptCommon+0x3e (FPO: [0,0,4])
ac49bda0 81a10858 00000002 000000d1 00000000 hal!HalpTimerClockInterrupt+0x1cb (FPO: [0,2] TrapFrame # ac49be38)
ac49beb8 81a239f3 00000000 ac49bf54 00200006 hal!HalEndSystemInterrupt+0xe8 (FPO: [Non-Fpo])
ac49beb8 0041be09 00000000 ac49bf54 00200006 hal!HalpTimerClockInterrupt+0x22b (FPO: [0,2] TrapFrame # ac49bf54)
0094c978 003c55f2 00000000 00000031 00ad55bc calc!WindowsCodecs_NULL_THUNK_DATA_DLB+0x79
0094c994 003c586b 00aded98 0094c9b8 003c599d calc!CUIController::displayEvent+0x76 (FPO: [1,1,4])
0094c9a0 003c599d 00ad5574 00adeea0 00aded98 calc!CDisplayEvent::deliver+0x1a (FPO: [Non-Fpo])
0094c9b8 003d5177 00aded98 5b5012f1 00000000 calc!CEventRegistry::fire+0x28 (FPO: [Non-Fpo])
0094c9e4 003d575a 00aded98 00adeea0 03bf38ec calc!CCalculatorState::SetBinaryDigitDisplay+0x75 (FPO: [Non-Fpo])
(side note: don't pay too much attention on the two trap frames above; it seems the first routine was interrupted as soon as it re-enabled interrupts using the STI instructios, so there are two trap frames rather than just one).
I'm reversing a malware on Mac OS with gdb.
Then I try to view a local variable in stack,Gdb tells me:"Cannot access memory at address 0xbffffd58".Why?
(gdb) ni
0x000086cc in ?? ()
=> 0x000086cc: 85 c0 test eax,eax
(gdb) i r
eax 0xbffffe0b -1073742325
ecx 0xbffffd58 -1073742504
edx 0x190fc 102652
ebx 0x868e 34446
esp 0xbffffb10 0xbffffb10
ebp 0xbffffb58 0xbffffb58
esi 0x1 1
edi 0x17e9a 97946
eip 0x86cc 0x86cc
eflags 0x302 [ TF IF ]
cs 0x1b 27
ss 0x23 35
ds 0x23 35
es 0x23 35
fs 0x0 0
gs 0xf 15
(gdb) ni
0x000086ce in ?? ()
=> 0x000086ce: 74 e4 je 0x86b4
(gdb) ni
0x000086d0 in ?? ()
=> 0x000086d0: 80 38 2d cmp BYTE PTR [eax],0x2d
(gdb) x/3cb $eax
0xbffffe0b: Cannot access memory at address 0xbffffe0b
(gdb) ni
0x000086d3 in ?? ()
=> 0x000086d3: 75 df jne 0x86b4
(gdb) ni
0x000086b4 in ?? ()
=> 0x000086b4: bf ff ff ff ff mov edi,0xffffffff
(gdb)
Well,I think it is a bug in GDB:
(gdb) x/12i $pc-0x2a
0x2473: push ebx
0x2474: call 0x2479
0x2479: pop ebx
0x247a: sub esp,0x34
0x247d: lea edx,[ebp-0x19]
0x2480: mov DWORD PTR [esp],edx
0x2483: mov DWORD PTR [esp+0x8],0x6
0x248b: lea eax,[ebx+0x15a3e]
0x2491: mov DWORD PTR [esp+0x4],eax
0x2495: call 0xd900
0x249a: mov DWORD PTR [esp],eax
=> 0x249d: call 0x300b3
(gdb) x/10xb $eax
0xbffffcdf: Cannot access memory at address 0xbffffcdf
(gdb) x/1xw $esp
0xbffffcc0: 0xbffffcdf
(gdb) x/10xb 0xbffffcdf
0xbffffcdf: 0x2f 0x74 0x6d 0x70 0x00 0x05 0x7e 0x01
0xbffffce7: 0x00 0x27
(gdb) ni
0x000300b3 in ?? ()
=> 0x000300b3: e8 48 42 de 8f call 0x8fe14300
(gdb)
you see? Examine the same address twice,I get two different results.
And then,I input 'ni' command ,GDB doesn't stepover!
Gdb doesn't work well on Mac OS X?
I am trying to write a simple program that prints out a C string without using one of the linux system calls or the standard C library functions. This is for learning purposes only, and I would never do this in production (unless I got really good at it =)).
First my system info:
[mehoggan#fedora sandbox-print_chars]$ uname -a
Linux fedora.laptop 2.6.35.14-106.fc14.i686.PAE #1 SMP Wed Nov 23 13:39:51 UTC 2011 i686 i686 i386 GNU/Linux
[mehoggan#fedora sandbox-print_chars]$ gcc --version
gcc (GCC) 4.5.1 20100924 (Red Hat 4.5.1-4)
Copyright (C) 2010 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Next the code:
#include <unistd.h>
#include <sys/syscall.h>
void main()
{
char *str = "Hello World";
while(*(str) != '\0') {
//printf("%c", *(str++));
//syscall(__NR_write, 1, *(str++), 1);
__asm__( "movl %0, %%ecx" :"=c" (str));
__asm__( "movl $0X4, %eax" );
__asm__( "movl $0X1, %ebx" );
__asm__( "movl $0X1, %edx" );
__asm__( "int $0X80" );
str++;
}
return;
}
Compiled with the following makefile:
all: sandbox_c
sandbox_c: sandbox.c
gcc -Wall -o sandbox_c ./sandbox.c
gcc -S -Wall -o sandbox_c.asm ./sandbox.c
Things compile just fine, I just cant get the syntax right to get the thing to work. Your corrections are greatly appreciated, but if you could also point me to how you obtained the solution that would be great. I am trying to get better at using the man pages etc.
ADDITION
Running the executable through gdb I can see that ecx is not being pointed at the right address:
[mehoggan#fedora sandbox-print_chars]$ gdb ./sandbox_c
GNU gdb (GDB) Fedora (7.2-52.fc14)
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "i686-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/mehoggan/Code/Assembly/sandbox/sandbox-print_chars/sandbox_c...done.
(gdb) break sandbox.c:8
Breakpoint 1 at 0x80483a2: file ./sandbox.c, line 8.
(gdb) run
Starting program: /home/mehoggan/Code/Assembly/sandbox/sandbox-print_chars/sandbox_c
Breakpoint 1, main () at ./sandbox.c:8
8 while(*(str) != '\0') {
Missing separate debuginfos, use: debuginfo-install glibc-2.13-2.i686
(gdb) step
11 __asm__( "movl %0, %%ecx" :"=c" (str));
(gdb) info registers
eax 0x48 72
ecx 0x34092fad 873017261
edx 0x1 1
ebx 0x567ff4 5668852
esp 0xbffff2a4 0xbffff2a4
ebp 0xbffff2b8 0xbffff2b8
esi 0x0 0
edi 0x0 0
eip 0x80483a4 0x80483a4 <main+16>
eflags 0x200206 [ PF IF ID ]
cs 0x73 115
ss 0x7b 123
ds 0x7b 123
es 0x7b 123
fs 0x0 0
gs 0x33 51
(gdb) step
12 __asm__( "movl $0X4, %eax" );
(gdb) info registers
eax 0x48 72
ecx 0x34092fad 873017261
edx 0x1 1
ebx 0x34092fad 873017261
esp 0xbffff2a4 0xbffff2a4
ebp 0xbffff2b8 0xbffff2b8
esi 0x0 0
edi 0x0 0
eip 0x80483ab 0x80483ab <main+23>
eflags 0x200206 [ PF IF ID ]
cs 0x73 115
ss 0x7b 123
ds 0x7b 123
es 0x7b 123
fs 0x0 0
gs 0x33 51
(gdb) step
13 __asm__( "movl $0X1, %ebx" );
(gdb) info registers
eax 0x4 4
ecx 0x34092fad 873017261
edx 0x1 1
ebx 0x34092fad 873017261
esp 0xbffff2a4 0xbffff2a4
ebp 0xbffff2b8 0xbffff2b8
esi 0x0 0
edi 0x0 0
eip 0x80483b0 0x80483b0 <main+28>
eflags 0x200206 [ PF IF ID ]
cs 0x73 115
ss 0x7b 123
ds 0x7b 123
es 0x7b 123
fs 0x0 0
gs 0x33 51
(gdb) step
14 __asm__( "movl $0X1, %edx" );
(gdb) info registers
eax 0x4 4
ecx 0x34092fad 873017261
edx 0x1 1
ebx 0x1 1
esp 0xbffff2a4 0xbffff2a4
ebp 0xbffff2b8 0xbffff2b8
esi 0x0 0
edi 0x0 0
eip 0x80483b5 0x80483b5 <main+33>
eflags 0x200206 [ PF IF ID ]
cs 0x73 115
ss 0x7b 123
ds 0x7b 123
es 0x7b 123
fs 0x0 0
gs 0x33 51
(gdb) step
15 __asm__( "int $0X80" );
(gdb) info registers
eax 0x4 4
ecx 0x34092fad 873017261
edx 0x1 1
ebx 0x1 1
esp 0xbffff2a4 0xbffff2a4
ebp 0xbffff2b8 0xbffff2b8
esi 0x0 0
edi 0x0 0
eip 0x80483ba 0x80483ba <main+38>
eflags 0x200206 [ PF IF ID ]
cs 0x73 115
ss 0x7b 123
ds 0x7b 123
es 0x7b 123
fs 0x0 0
gs 0x33 51
(gdb) step
16 str++;
(gdb) info registers
eax 0xfffffff2 -14
ecx 0x34092fad 873017261
edx 0x1 1
ebx 0x1 1
esp 0xbffff2a4 0xbffff2a4
ebp 0xbffff2b8 0xbffff2b8
esi 0x0 0
edi 0x0 0
eip 0x80483bc 0x80483bc <main+40>
eflags 0x200206 [ PF IF ID ]
cs 0x73 115
ss 0x7b 123
ds 0x7b 123
es 0x7b 123
fs 0x0 0
gs 0x33 51
Try this:
__asm__ volatile ( "movl $0X4, %eax
movl $0X1, %ebx
movl $0X1, %edx
int $0X80"
: /* outputs: */ /* none */
: /* inputs: */ "c" (str)
: /* clobbers: */ "eax", "ebx", "edx");
I've not tested it, but the syntax looks right. You might need to add some more "clobbers" if the syscall overwrites anything else - check the documentation.
Breaking it down:
There's no need to move %0 to %ecx because the "c" constraint already did that.
str is an input, but you had it as an output.
volatile tells the compiler not to remove it - it has no output so the compiler might think it can.
You need to tell the compiler what registers are 'clobbered' by the code. I've added the obvious ones, but the system call might clobber more?
You need to put them in all one asm or the compiler might think it can move them around.
For whatever it's worth, calling "int 0x80" is making a system call.
You're just not using "printf", or using the standard C library wrappers for Linux syscalls.
And there's nothing wrong with that :)
Anyway, here's a complete example illustrating EXACTLY what you're after:
http://asm.sourceforge.net/intro/hello.html
'Hope that helps ... and have fun!