I'm not talking about the call stack.
I want to count how many times a certain function is called when at the address hold by ESP there is a certain value. Before you tell me to check the return address, I'm not interested in that - the return address is at ESP+4 in this case, [ESP] holding a value that is popped before the function will return. Details unimportant.
I can count function calls with the following syntax:
bp MyFunction "r #$t0 = #$t0 + 1; r #$t0; gc"
I can display the double word at [ESP] by adding
dd $csp L1
to the above command.
The problem is that there are quite a lot of calls and I'm only interested in certain calls and tracking them down manually after each break point is annoying and time consuming.
I'm still getting used with WinDbg's syntax. How should the condition look in my .if statement?
I tried some crazy things like
.if( (dd $csp L1) == 2 )
But that is obviously wrong.
I also though about setting the breakpoint somewhere in the function after the value at [ESP] is moved in a local variable (something like bp MyFunction+eip_after_assignment), but that is a bit too late. I think I can work with that, but it will make things simpler if I could just check [ESP] at the beginning.
0:000> lsa .
2: int dummy=0;
3: void useless(int in) {
4: dummy=in;
5: }
> 6: void main(void) {
7: for(int i=0;i<0xffffffff;i++)
8: useless(i);
9: }
0:000> uf countfunc!useless
countfunc!useless [c:\countfunc.cpp # 3]:
3 00401000 55 push ebp
3 00401001 8bec mov ebp,esp
4 00401003 8b4508 mov eax,dword ptr [ebp+8]
4 00401006 a320bb4000 mov dword ptr [countfunc!dummy (0040bb20)],eax
5 0040100b 5d pop ebp
5 0040100c c3 ret
0:000> bl
0:000> bp 0040100b ".if ( poi(#$csp+8) != 1337 ) {gc}"
0:000> .bpcmds
bp0 0x0040100b ".if ( poi(#$csp+8) != 1337 ) {gc}";
0:000> g
> eax=00001337 ebx=7ffdf000 ecx=00001337 edx=0040c340 esi=00000000
> edi=0098f6ee eip=0040100b esp=0013ff68 ebp=0013ff68 iopl=0 nv
> up ei pl nz ac po cy cs=001b ss=0023 ds=0023 es=0023 fs=003b
> gs=0000 efl=00000213 countfunc!useless+0xb: 0040100b 5d
> pop ebp
0:000> ?? in
int 0n4919
0:000> dv
in = 0n4919
0:000> ? 0n4919/1
Evaluate expression: 4919 = 00001337
a bit more complex conditional break on same code conditional breaks do take a lot of time debugging time sensitive code can be quiet challenging
0:000> r $t0 = 0; bp 0040100b ".if ( poi(#$csp+8) != #$t0*1337 ) {gc} .else { .echotime ;? poi(#$csp+8) ; r$t0 = #$t0+1 ;gc }"
0:000> .bpcmds
bp0 0x0040100b ".if ( poi(#$csp+8) != #$t0*1337 ) {gc} .else { .echotime ;? poi(#$csp+8) ; r$t0 = #$t0+1 ;gc }";
0:000> .echotime
Debugger (not debuggee) time: Tue Sep 30 12:12:15.890 2014
0:000> g
Debugger (not debuggee) time: Tue Sep 30 12:12:24.062 2014
Evaluate expression: 0 = 00000000
Debugger (not debuggee) time: Tue Sep 30 12:12:32.578 2014
Evaluate expression: 4919 = 00001337
Debugger (not debuggee) time: Tue Sep 30 12:12:41.093 2014
Evaluate expression: 9838 = 0000266e
Debugger (not debuggee) time: Tue Sep 30 12:12:49.609 2014
Evaluate expression: 14757 = 000039a5
Debugger (not debuggee) time: Tue Sep 30 12:12:58.156 2014
Evaluate expression: 19676 = 00004cdc
Debugger (not debuggee) time: Tue Sep 30 12:13:06.687 2014
Evaluate expression: 24595 = 00006013
Debugger (not debuggee) time: Tue Sep 30 12:13:15.218 2014
Evaluate expression: 29514 = 0000734a
Debugger (not debuggee) time: Tue Sep 30 12:13:23.765 2014
Evaluate expression: 34433 = 00008681
Debugger (not debuggee) time: Tue Sep 30 12:13:32.828 2014
Evaluate expression: 39352 = 000099b8
Debugger (not debuggee) time: Tue Sep 30 12:13:40.906 2014
Evaluate expression: 44271 = 0000acef
this simple code may take 86 days to complete if it continued like this it seems it takes ~8.5 seconds to process 4919 function calls in windbg
Related
I'm new with assembly language (8086 Program) and I am trying to create a program that display a greeting depending on system date and time. Like if the system date is December 25 then the program will print "Merry Christmas" or if January 1 then it's "Happy New Year". If it just a regular day / no holiday then just print a "Good day". On system time, probably display a "Good Evening" or "Good Morning".
So far, I learned how to get and display the system time and date. Now, I am wondering how can I apply conditionals (if-else) on it.
Assuming you've asked the date from DOS using function 2Bh, the day will be in DL and the month in DH. Checking for Christmas day is simply writing cmp dx, 0C19h.
Get inspired by next example:
mov si, Xmas
cmp dx, 0C19h ; 25 dec
je GoPrint
mov si, NewY
cmp dx, 0101h ; 01 jan
je GoPrint
...
GoPrint:
mov dx, si
mov ah, 09h ; DOS.PrintString
int 21h
...
Xmas: db 'Merry ...', 13, 10, '$'
NewY: db 'Happy ...', 13, 10, '$'
For 'Good day' vs 'Good evening', you can apply similar code to the time (hours) in the CH register that you get from invoking the DOS function 2Ch.
I want to do something like break at Process!Function+0x66 but only if [RDX + 0x01c] == 1.
What would the syntax of breakpoint like this be?
evaluate with ? Process!Function+0x66
copy the result for using in breakpoint 0x12345678`90abcdef
bp 0x12345678`90abcdef ".if ( poi(#rdx+0x1c) != 1) {gc}"
a sample flow
0:000> ? msvcrt!memcpy+0x40
Evaluate expression: 140735863146304 = 00007fff`9f214740
0:000> u msvcrt!memcpy+0x40 l1
msvcrt!memcpy+0x40:
00007fff`9f214740 8a0411 mov al,byte ptr [rcx+rdx]
0:000> bp 00007fff`9f214740 " .if( poi(#rcx+#rdx) != 0x20) {gc}"
0:000> bl 0 e 00007fff`9f214740 0001 (0001) msvcrt!memcpy+0x40 ".if( poi(#rcx+#rdx) != 0x20) {gc}"
0:000> g
Microsoft (R) Windows Debugger Version 10.0.17763.132 AMD64
msvcrt!memcpy+0x40:
00007fff`9f214740 8a0411 mov al,byte ptr [rcx+rdx] ds:000001d6`1ebc6ac1=20
0:000> .lastevent
Last event: 724.1718: Hit breakpoint 0
debugger time: Wed Jun 16 00:25:26.965 2021
0:000> g
msvcrt!memcpy+0x40:
00007fff`9f214740 8a0411 mov al,byte ptr [rcx+rdx] ds:000001d6`20407c4a=20
0:000> .lastevent
Last event: 724.1718: Hit breakpoint 0
debugger time: Wed Jun 16 00:25:45.283 2021
0:000>
i capture this 64-bit time format from a game and trying to understand it.
I can not use a date delta because every now and then the value totally changes and even becomes negative as seen below.
v1:int64=-5990085973098618987; //2021-01-25 13:30:00
v2:int64=-5990085973321147595; //4 mins later
v3:int64=6140958949625363349; //7 mins later
v4:int64=6140958948894898101; //11 mins later
v5:int64=-174740204032730139; //16 mins later
v6:int64=-174740204054383467; //18 mins later
v7:int64=-6490439358095090795; //23 mins later
I tried to split the 64-bit into two 32-bit containers to get low and high part. still strange values.
I also tried using pdouble(#value)^ to get float value of the 64-bit data, still strange values.
So kind of running out of ideas, maybe some kind of bitfield data or something else going on.
hipart: -1394675573 | lopart: 1466441621 | hex: acdef08b|57681f95 | swap: -7701322112560996692
hipart: -1394675573 | lopart: 1243913013 | hex: acdef08b|4a249b35 | swap: 3862721007994330796
hipart: 1429803424 | lopart: -458425451 | hex: 553911a0|e4acfb95 | swap: -7639322244965910187
hipart: 1429803424 | lopart: -1188890699 | hex: 553911a0|b922f7b5 | swap: -5334757052947285675
hipart: -40684875 | lopart: -760849435 | hex: fd9332b5|d2a65be5 | swap: -1919757392230050819
hipart: -40684875 | lopart: -782502763 | hex: fd9332b5|d15bf495 | swap: -7641381711494605827
hipart: -1511173174 | lopart: -1467540587 | hex: a5ed53ca|a8871b95 | swap: -7702413578668347995
Any ideas welcomed, thanks in advance
//mbs
--EDIT: So far, thanks to Martin Rosenau we are able to encode like this:
func mulproc_nfsw(i:int64;key:uint32):int64;
begin
if (blnk i) or (blnk key) then exit;
p:pointer=#i;
hi:uint32=uint32(p+4)^; //30864159 (hex: 01d6f31f)
lo:uint32=uint32(p)^; //748455936 (hex: 2c9c8800)
hi64:int64=hi*key; //0135b55a acdef08b <-- keep
lo64:int64=lo*key; //1d566e0b a65f2800 <-- keep
q:pointer=#result; //-5990085971773806592
uint32(q+4)^:=hi64; //acdef08b
uint32(q)^:=lo64; //a65f2800
end;
func encode_time_nfsw(j:juncture):int64;
begin
if blnk j then exit; //input: '2021-01-25 13:37:07'
key:uint32=$A85A2115; //encode key
ft:int64=j.filetime; //hex: 01d6f31f 2c9c8800
result:=mulproc_nfsw(ft,key);
end;
--EDIT2: Finally, thanks to fpiette we are able to decode also:
func decode_time_nfsw(i:int64):juncture;
begin
if blnk i then exit; //input: -5990085971773806592
key:uint32=$3069263D; //decode key
ft:int64=mulproc_nfsw(i,key);
result.setfiletime(ft);
end;
I checked my suspicion that the high and the low 32 bits are simply multiplied by A85A2115 (hex):
We get a FILETIME structure. Then we perform a 32x32->32 bit multiplication (this means we throw away the high 32 bits of the 64 bits result) of the high and the low word independently.
Example:
25 Jan 2021 13:37:07 (and some milliseconds)
Unencrypted FILETIME:
High dword = 1D6F31F (hex)
Low dword = 2C9CA481 (hex)
Multiplication
High dword: 1D6F31F * A85A2115 = 135B55AACDEF08B (hex)
Low dword: 2C9CA481 * A85A2115 = 1D5680CA57681F95 (hex)
Now only take the low 32 bits of the results:
High dword: ACDEF08B (hex)
Low dword: 57681F95 (hex)
Unfortunately, I don't know how to do the the "reverse operation"; I did it by searching for the result in a loop with the following pseudo-code:
encryptedValue = 57681F95 (hex)
originalValue = 0
product = 0
while product not equal to encryptedValue
// 32-bit addition discarding carry:
product = product + A85A2115 (hex)
originalValue = originalValue + 1
end_of_while_loop
We get the following results:
25 Jan 2021 13:37:07 => acdef08b|57681f95
25 Jan 2021 13:40:51 => acdef08b|4a249b35
25 Jan 2021 13:45:07 => 553911a0|e4acfb95
25 Jan 2021 13:49:03 => 553911a0|b922f7b5
25 Jan 2021 13:53:53 => fd9332b5|d2a65be5
25 Jan 2021 13:55:50 => fd9332b5|d15bf495
25 Jan 2021 14:00:39 => a5ed53ca|a8871b95
Addendum
The reverse operation seems to be done by multiplying with 3069263D (hex) (and only using the low 32 bits).
Encrypting:
2C9CA481 * A85A2115 = 1D5680CA57681F95
=> Result: 57681F95
Decrypting:
57681F95 * 3069263D = 10876CAF2C9CA481
=> Result: 2C9CA481
I have some breakpoint "pairs," and I'd like to measure the time in between when they are hit.
The simplest thing that would allow me to do this is to include some sort of timestamp (even if it's just clock ticks or something) in the .printf I use when the breakpoint is hit.
I could use the pseudo registers $tid and $dbgtime in the breakpoint code. When I do, the performance really suffers.
bp1000 ucrtbase!malloc ".printf \"[0x%08x] [ucrtbase] [0x%04x] [0x%08x] malloc(%d): \", $dbgtime, $tid, dwo(#esp), dwo(#esp+4); gc "
When the same code is used (without using meaningful values for timestamp and thread id), things work much better.
bp1000 ucrtbase!malloc ".printf \"[0x%08x] [ucrtbase] [0x%04x] [0x%08x] malloc(%d): \", 0, 0, dwo(#esp), dwo(#esp+4); gc "
Is there some other (high-performance) way to get this information? The current time is more valuable than the thread ID. I can always make the breakpoint only apply to a specific thread so that emitting the ID is only sugar.
try this
0:000> bp ucrtbase!malloc "~# ; .echotime ; dd #$csp l2 ; gc ;"
0:000> bl
0 e 00007ff8`ab61c9e0 0001 (0001) 0:**** ucrtbase!malloc "~# ; .echotime ; dd #$csp l2 ; gc ;"
0:000> g
. 0 Id: 1a84.1f14 Suspend: 1 Teb: 00000018`f49d1000 Unfrozen
Start: cdb!wmainCRTStartup (00007ff6`efd2bbf0)
Priority: 0 Priority class: 32 Affinity: f
Debugger (not debuggee) time: Wed Aug 7 22:17:44.992 2019
00000018`f47eeb58 ab622762 00007ff8
. 0 Id: 1a84.1f14 Suspend: 1 Teb: 00000018`f49d1000 Unfrozen
Start: cdb!wmainCRTStartup (00007ff6`efd2bbf0)
Priority: 0 Priority class: 32 Affinity: f
Debugger (not debuggee) time: Wed Aug 7 22:17:44.992 2019 (UTC + 5:30)
00000018`f47eeb08 ab622762 00007ff8
I want to make changes to some EDBs and then find out how the IDBs changed as a result.
The docs say that the query stage comes after the final stage and "has access to the effects of stage FINAL". But if I run
query '_(id) <- ^level(id; _).'
(where level is an IDB) I get
block block_1Z7PZ61E: line 2: error: predicate level is an IDB, therefore deltas for it will not be available until stage final. (code: STAGE_INITIAL_IDB_DELTA)
^level(id; _).
^^^^^^^^^^^^^
1 ERROR
BloxCompiler reported 1 error in block 'block_1Z7PZ61E'
I also tried following the diff predicate example. But this
query '_(id) <- (level\level#prev)(id; _).'
causes a syntax error:
block block_1Z80EFSZ: line 2: error: illegal character 'U+005C' (code: ILLEGAL_CHARACTER)
(level\level#prev)(id; _).
^
block block_1Z80EFSZ: line 2: error: unexpected token 'level' (code: UNEXPECTED_TOKEN)
(level\level#prev)(id; _).
^^^^^
block block_1Z80EFSZ: line 2: error: unexpected token ')' (code: UNEXPECTED_TOKEN)
(level\level#prev)(id; _).
^
block block_1Z80EFSZ: line 2: error: unexpected token ';' (code: UNEXPECTED_TOKEN)
(level\level#prev)(id; _).
^
4 ERRORS
BloxCompiler reported 4 errors in block 'block_1Z80EFSZ'
Unfortunately the diff predicate functionality is not yet released (as of Dec 2016). We've noted that as a documentation bug to fix. The feature is expected in LB 4.4 in Q1 2017.
Here's a simple example for printing or querying the values in the IDB predicate after changes to the EDB. You don't need to use delta logic in this case.
[dan#glycerine Fri Dec 30 09:55:54 ~/Temp]
$ cat foo.logic
foo(x), foo_id(x: y) -> int(y).
edb[x] = y -> foo(x), int(y).
idb[x] = y -> foo(x), int(y).
idb[x] = y <- edb[x] + 10 = y.
[dan#glycerine Fri Dec 30 09:56:33 ~/Temp]
$ lb create --overwrite foo && lb addblock foo --name foo --file foo.logic && lb exec foo '+foo(x), +foo_id[x] = 1, +edb[x] = 5.'
created workspace 'foo'
added block 'foo'
[dan#glycerine Fri Dec 30 09:57:23 ~/Temp]
$ lb print foo edb
[10000000005] 1 5
[dan#glycerine Fri Dec 30 09:57:28 ~/Temp]
$ lb print foo idb
[10000000005] 1 15
[dan#glycerine Fri Dec 30 09:57:32 ~/Temp]
$ lb exec foo '^edb[x] = 15 <- foo_id[x] = 1.'
[dan#glycerine Fri Dec 30 09:57:54 ~/Temp]
$ lb print foo idb
[10000000005] 1 25
[dan#glycerine Fri Dec 30 09:57:55 ~/Temp]
$ lb query foo '_[x] = edb[x].'
/--------------- _ ---------------\
[10000000005] 1 15
\--------------- _ ---------------/
I can think of a couple options for watching changes more as they happen. In once case you could create a watcher predicate and add values to it like this.
watcher(x, y) -> int(x), int(y).
^watcher(x, y) <- foo_id[x] = id, ^idb[id] = y.
That could be enhanced to have its own entity and timestamp...
Another way, if you are using web services to make the EDB updates, is to use
lb web-server monitor -w foo idb
to watch a list of predicates.