PDA

View Full Version : Locating reference to memory address in stack of another thread


shasderias
June 30th, 2010, 11:24
I am trying to write a program that reads some data from another program which is basically an array of 1024 16bit integers. Said program spins off a thread, the thread does some I/O with hardware and the data retrieved is stored into the array. The thread that does the reading appears to be totally self-contained, it calls another DLL that does the hardware I/O and updates the screen itself. Never communicating with the main thread. The data I need is thus stored only in a single location.

The problem is thus: the data is stored in the stack of the thread and changes upon each program reload. How can I retrieve the address from within my own program.

What does not (appear) to work:
1) searching for a pointer to any point in thread's data block/stack, the thread does truly appear to be self-contained, at no point in time is there a pointer to any address within the thread's stack/data block that does not reside in the thread's own stack/data block.

2) upon each restart, the memory allocated for the thread changes, thus I am unable to locate a static offset

What I have considered:
1) Trying to locate the CreateThread function, finding the address in which the handle to the thread is stored, reading that, then attempting to retrieve the thread's data block, but I am unable to determine how I can go from thread handle -> address of thread's data block

2) injecting code/patching the program to somehow write out the memory location. The program I am working with is used for a realtime application, I do not want to risk crashing it

Any advice is appreciated, thank you

Some extra information I am unsure if it would be useful:
1) Program written in Delphi6
2) The data is always stored at a fixed offset from the thread's stack, if I can somehow get the base address of the thread, I'd be fine
3) There are multiple threads spun off for different purposes, considered enumerating the threads, picking the one that isn't the main thread, does not work for this reason
4) Data block of thread has a pointer to the thread's stack, thus the address of the data block would work just fine

BanMe
June 30th, 2010, 22:30
Code:

HANDLE WINAPI CreateThread(
__in_opt LPSECURITY_ATTRIBUTES lpThreadAttributes,
__in SIZE_T dwStackSize,
__in LPTHREAD_START_ROUTINE lpStartAddress,
__in_opt LPVOID lpParameter,
__in DWORD dwCreationFlags,
__out_opt LPDWORD lpThreadId
);


You can breakpoint CreateThread(if you can debug the process that is)then you would need to filter out the lpStartAddress of each call to the function (and maybe the lpParameter passed just for further identification) then you could develop a 'signature' to scan for the function you know the thread uses and has your specific data or 'will' have it. You can then either hook the function and gather the data that way or you can use Stackwalk64() to walk the stack of all threads and locate your data in a more meticulous way

I think the more reliable method is the hook cause it update on call and not user demand but to each his\her own.

regards BanMe

Kayaker
July 1st, 2010, 00:02
Hi

Just a few ideas. You could probably manage that with a driver, making use of KeStackAttachProcess. Once you've attached to the process you'll need to reference the correct thread. You could parse through all the threads in the process and cross reference with the known Win32StartAddress to get the correct thread object. Or, if you've previously determined the thread handle from usermode, you should be able to convert that to the correct thread object (ETHREAD structure) with ObReferenceObjectByHandle.

ETHREAD.TEB will reference NT_TIB and NT_TIB.StackBase will give you the stack reference offset you need (EBP may be directly available as well through some combination of structure offsets) . Since you're attached to the process you should be able to read it.

I did a little test under Softice and was able to find a local variable on a thread stack by manually parsing the ETHREAD in that manner.

Interested in any other strategies.

Kayaker

shasderias
July 1st, 2010, 01:00
Quote:
[Originally Posted by BanMe;87098]
Code:

HANDLE WINAPI CreateThread(
__in_opt LPSECURITY_ATTRIBUTES lpThreadAttributes,
__in SIZE_T dwStackSize,
__in LPTHREAD_START_ROUTINE lpStartAddress,
__in_opt LPVOID lpParameter,
__in DWORD dwCreationFlags,
__out_opt LPDWORD lpThreadId
);


You can breakpoint CreateThread(if you can debug the process that is)then you would need to filter out the lpStartAddress of each call to the function (and maybe the lpParameter passed just for further identification) then you could develop a 'signature' to scan for the function you know the thread uses and has your specific data or 'will' have it.

Yup, I can debug the process no problem, the relevant CreateThread call always passes in the same value for ThreadFunction. I also know the function that makes the external DLL call. Should I try hooking either the external DLL call instead?

I am still not quite sure how I should do this from within my own program though, specifically how do I scan for the function, or am I supposed to set a breakpoint from my own program on the process? A pointer at the correct direction would be appreciated.

Quote:

You can then either hook the function and gather the data that way or you can use Stackwalk64() to walk the stack of all threads and locate your data in a more meticulous way

I think the more reliable method is the hook cause it update on call and not user demand but to each his\her own.

regards BanMe


Indeed, looks like the hook is a better solution, given that the application calls out once every second or so.

I'm guessing my problem is, I can see all the information I need in Olly, I just am not sure how to translate that to code.

Quote:

Kayaker
Hi

Just a few ideas. You could probably manage that with a driver, making use of KeStackAttachProcess. Once you've attached to the process you'll need to reference the correct thread. You could parse through all the threads in the process and cross reference with the known Win32StartAddress to get the correct thread object. Or, if you've previously determined the thread handle from usermode, you should be able to convert that to the correct thread object (ETHREAD structure) with ObReferenceObjectByHandle.

ETHREAD.TEB will reference NT_TIB and NT_TIB.StackBase will give you the stack reference offset you need (EBP may be directly available as well through some combination of structure offsets) . Since you're attached to the process you should be able to read it.

I did a little test under Softice and was able to find a local variable on a thread stack by manually parsing the ETHREAD in that manner.

Interested in any other strategies.

Kayaker


Apologies, unfamiliar with Windows drivers: basically I would need to write a small driver that grabs the necessary data (I get the gist of the procedure you've outlined), and/or somehow retrieve a handle to the process in usermode, pass that to the driver, which would then call ObReferenceObjectByHandle, giving me an ETHREAD object, which I can use to locate the memory offsets I need. Following which I can read the process's memory from usermode to get the data structure out. Is that right?

Thanks for the help Banme and Kayaker (:

aqrit
July 1st, 2010, 01:58
http://wiki.tcwonline.org/Signature_Scanning

Quote:
Data block of thread has a pointer to the thread's stack


Is the address of the data block being passed as lpParameter to the CreateThread function?

shasderias
July 1st, 2010, 02:04
Quote:
[Originally Posted by aqrit;87101]http://wiki.tcwonline.org/Signature_Scanning



Is the address of the data block being passed as lpParameter to the CreateThread function?


Nope, appears to be the return value of a function called a few lines up. Thanks, reading (:

edit: That was what I was thinking, scanning for a series of bytes unique to the thread's stack/data block. Looking into that now, failing which, will probably try to hook the I/O dll's function/function that calls the I/O function.

edit2: I don't quite understand how getting the address of the function helps me. The function is always located at a fixed offset, its the thread's data block/stack that shifts around.

BanMe
July 1st, 2010, 10:02
Quote:

I also know the function that makes the external DLL call. Should I try hooking either the external DLL call instead?


You can do that.

Quote:

How do I scan for the function, or am I supposed to set a breakpoint from my own program on the process? A pointer at the correct direction would be appreciated.


well the answer to that is Dll or memory Injection you cant rely on your own process to have this data and if you set a breakpoint on the function from your code you would also have to add a handler to handler the Breakpoint you wrote in said process..unless you want it to break to olly..or w/e

lets do a little sample of how to find code by scanning for it (In our own process)
Code:

2147102C > $ 68 48010000 PUSH 148
21471031 . 68 28224721 PUSH affectio.21472228
21471036 . E8 11050000 CALL affectio.__SEH_prolog
2147103B . 33DB XOR EBX,EBX
2147103D . 895D AC MOV DWORD PTR SS:[EBP-54],EBX
21471040 . 33C0 XOR EAX,EAX
21471042 . 8D7D B0 LEA EDI,DWORD PTR SS:[EBP-50]
21471045 . AB STOS DWORD PTR ES:[EDI]
21471046 . AB STOS DWORD PTR ES:[EDI]
21471047 . 895D 94 MOV DWORD PTR SS:[EBP-6C],EBX
2147104A . 33C0 XOR EAX,EAX
2147104C . 8D7D 98 LEA EDI,DWORD PTR SS:[EBP-68]
2147104F . AB STOS DWORD PTR ES:[EDI]
21471050 . AB STOS DWORD PTR ES:[EDI]
21471051 . 66:895D D8 MOV WORD PTR SS:[EBP-28],BX
21471055 . 33C0 XOR EAX,EAX
21471057 . 8D7D DA LEA EDI,DWORD PTR SS:[EBP-26]
2147105A . AB STOS DWORD PTR ES:[EDI]
2147105B . 66:AB STOS WORD PTR ES:[EDI]
2147105D . C745 A0 964000>MOV DWORD PTR SS:[EBP-60],4096
21471064 . 33C0 XOR EAX,EAX
21471066 . 8D7D A4 LEA EDI,DWORD PTR SS:[EBP-5C]
21471069 . AB STOS DWORD PTR ES:[EDI]
2147106A . 66:899D FCFEFF>MOV WORD PTR SS:[EBP-104],BX
21471071 . 6A 7E PUSH 7E ; /n = 7E (126.)
21471073 . 53 PUSH EBX ; |c => 00
21471074 . 8D85 FEFEFFFF LEA EAX,DWORD PTR SS:[EBP-102] ; |
2147107A . 50 PUSH EAX ; |s
2147107B . E8 22060000 CALL affectio._memset ; \_memset
21471080 . 66:899D A8FEFF>MOV WORD PTR SS:[EBP-158],BX
21471087 . 6A 52 PUSH 52 ; /n = 52 (82.)
21471089 . 53 PUSH EBX ; |c
2147108A . 8D85 AAFEFFFF LEA EAX,DWORD PTR SS:[EBP-156] ; |
21471090 . 50 PUSH EAX ; |s
21471091 . E8 0C060000 CALL affectio._memset ; \_memset
21471096 . 83C4 18 ADD ESP,18
21471099 . 899D 7CFFFFFF MOV DWORD PTR SS:[EBP-84],EBX
...


ok so for this eample we want to find memset.
so the opcode just after memset are..

Code:

83C4 18 ADD ESP,18


heres the signature that we will find this code

Code:

BYTE FindThis[] = {0x83,0xc4,0,0x04};


// this says find opcodes 0x83 and 0xc4 in consecutive order
//ie the 0 after the opcodes, after our function finds these opcodes it minus's 0x4
//for the address they where found at to get the function call to memset
This functionality is illustrated in this code
Code:

//This Code is a mix of methods ive come accross
//GetFunctionLength is a knock off of what darawk did with a similiar name..can be googled..
//Signature Scanning code I think I originally saw this technique by opcodex90..
//secondly this dynamic find methodology was first implemented in CsrWalker by ep_xoff or ug_north...
//I just combined them into something I found had a good amount of speed and get it right 99% of the time..
//(if you have a unique signature and it cant be found after the start of the function and is -(n)
//away from the address the opcodes where found at..
ULONG FindCode(__in ULONG dwStart,__in BYTE *FindThis)
{

ULONG ProcEnd = 0;
ProcEnd = GetFunctionLength((void*)dwStart);
ProcEnd += dwStart;
do
{
if(memcmp((void*)dwStart,&FindThis[0],sizeof(BYTE)) == 0 && memcmp((void*)(dwStart+sizeof(BYTE)+(ULONG)FindThis[2]),&FindThis[1],sizeof(BYTE)) == 0)
{
return (ULONG)(dwStart - (ULONG)FindThis[3]);
}
(BYTE*)dwStart++;
}while(dwStart < ProcEnd);
ProcEnd = 0;
return ProcEnd;
}


This code can be use without the functions Ive placed in it though it could end up scanning memory that doesnt like to be scanned.

Quote:

I don't quite understand how getting the address of the function helps me. The function is always located at a fixed offset, its the thread's data block/stack that shifts around.


The fact the function is static is a good thing this means you can reliably hook it without worry of false positives(scans for the function) ie hooking the wrong location and causing instability in the program..

but from what you describe i gather the pseudocode of said program

Code:

uint Buff[1024] = {0};//This is either passed by reference or it is a global block of memory
// or is just on the stack..
SomeOtherCode...
FunctionThatFillsBuff()
//here you want to hook..


The Data you want is there after return from said function, you can either place the hook or some other form of 'code derailment' instrumentation(VEH exceptions,SEH Exceptions,int3,PAGE_NO_ACCESS,PAGE_GAURD..to name a few..) If the hook is placed here you will have to emulate the opcodes overwritten in your hook before return to original program flow if the hook is placed on the function that will make it a bit more time consuming to build the hook routines..
If FunctionThatFills Buff returns in EAX your golden at this point if not in eax and just on stack
You can do as kayaker suggests with a lil modifiication(and not use a driver). NtCurrentTeb()->NtTib.StackBase could easily be used in the hook code to get that address

regards BanMe

shasderias
July 1st, 2010, 10:23
Quote:
[Originally Posted by BanMe;87104]The fact the function is static is a good thing this means you can reliably hook it without worry of false positives(scans for the function) ie hooking the wrong location and causing instability in the program..

but from what you describe i gather the pseudocode of said program

Code:

uint Buff[1024] = {0};//This is either passed by reference or it is a global block of memory
// or is just on the stack..
SomeOtherCode...
FunctionThatFillsBuff()
//here you want to hook..


The Data you want is there after return from said function, you can either place the hook or some other form of 'code derailment' instrumentation(VEH exceptions,SEH Exceptions,int3,PAGE_NO_ACCESS,PAGE_GAURD..to name a few..) If the hook is placed here you will have to emulate the opcodes overwritten in your hook before return to original program flow if the hook is placed on the function that will make it a bit more time consuming to build the hook routines..
If FunctionThatFills Buff returns in EAX your golden that this point if not in eax and just on stack
You can do as kayaker suggests with a lil modifiication(and not use a driver). NtCurrentTeb()->NtTib.StackBase could easily be used in the hook code to get that address

regards BanMe


Yup! Thats more or less exactly what the code looks like, and after some thought, that is probably the best way out. Finding the address and polling isn't as good a idea as the duration between each call to the IO function is variable (controlled by the user).

Buffer is created way earlier in the code, pointer to it is passed through several functions, before finally arriving here, ReadRegisters returns on AX I believe, value is stored somewhere else for some other purpose :

004C3205 CALL <JMP.&ML2DRV.ReadRegisters> ; ReadRegisters = function that does IO
004C320A MOV WORD PTR DS:[EDI+44],AX ;
004C320E JMP USW_up.004C32B8 ; goes somewhere else not as interesting

So. Currently reading up on hooking, but is what I need to learn and do something like:
1) inject my own block of code into the function (getting some space using VirtualAllocEx, then probably using CreateRemoteThread to run the code)
2) patch either 004C320A or 004C320E to jump into my block of code, push registers onto the stack
3) run my own code, NtCurrentTeb()->NtTib.StackBase gets me the address of the stack I want, use the offset, do whatever I need to do
4)
a) if patching 320A, move AX into EDI+44, then jump back to 320E
b) if patching 320E, jump to 004C32B8 when my code is done
5) restore the registers

Time to learn function hooking (:
Thanks again!

BanMe
July 1st, 2010, 10:40
It can work like that yes

good luck.

regards BanMe

shasderias
July 2nd, 2010, 13:07
Got it!

Wrote a little DLL, injected it into the process, patches the JMP to point at my own function, function gets called in context of relevant thread, do my memory shuffling, NtCurrentTeb->StackBase gives you the address of the current thread, do some offset calculations. Viola

Couldn't have done it without all your help. Thanks!