I disassembled an executable file with IDA pro. My goal is to hook the __usercall function. I know i need to wrap the __usercall with inine asm in my C++ code since i can't typedef thefunction. But i'm just not sure how this works.
I know the function takes an object as parameter and a *Vector3 as parameter in which the calculated value will be stored. Is there an easy way to tell which param will be what??
(sorry for the long code)
char __usercall sub_572EA0<al>(int a1<ecx>, int a2<edx>, int a3<eax>, int a4)
{
int v4; // edi#1
int v5; // esi#1
float v6; // eax#2
char v7; // al#3
int v8; // eax#5
char result; // al#11
int v10; // [sp+Ch] [bp-74h]#2
float v11; // [sp+10h] [bp-70h]#4
float v12; // [sp+14h] [bp-6Ch]#4
float v13; // [sp+18h] [bp-68h]#5
float v14; // [sp+1Ch] [bp-64h]#5
float v15; // [sp+20h] [bp-60h]#5
float v16; // [sp+24h] [bp-5Ch]#10
float v17; // [sp+28h] [bp-58h]#10
float v18; // [sp+2Ch] [bp-54h]#10
char v19; // [sp+30h] [bp-50h]#10
float v20; // [sp+3Ch] [bp-44h]#4
float v21; // [sp+40h] [bp-40h]#4
float v22; // [sp+44h] [bp-3Ch]#4
float v23; // [sp+54h] [bp-2Ch]#7
v4 = a3;
v5 = a1;
if ( a3 )
{
LODWORD(v6) = sub_55A920(*(_DWORD *)(a1 + 208));
if ( !sub_53ADD0(
v5,
v6,
v4,
(int)&v10) )
{
v7 = sub_4EC240(v4);
sub_4E3ED0(
1,
"Cannot find tag [%s]\n",
v7);
}
}
else
{
sub_572BE0();
*(float *)&v10 = *(float *)(v5 + 20) + v20;
v11 = *(float *)(v5 + 24) + v21;
v12 = *(float *)(v5 + 28) + v22;
}
v8 = dword_8FF12C;
v13 = flt_96A218;
v14 = flt_96A21C;
v15 = flt_96A220;
if ( dword_8FF12C == 2047 )
v8 = dword_8FF1D0;
sub_462250(
&v23,
&v13,
&v10,
&unk_82D6A0,
v8,
8400899);
if ( 1.0 == v23
|| (unsigned __int16)sub_492C50(&v23) == *(_DWORD *)(v5 + 208)
|| *(_UNKNOWN **)(v5 + 364) == &unk_FFFFFF
&& (v16 = v13
+ (*(float *)&v10 - v13)
* v23,
v17 = (v11 - v14) * v23 + v14,
v18 = v23 * (v12 - v15) + v15,
sub_4C35B0(
&v16,
v5 + 20,
v5 + 32,
&v19),
sub_432850(
*(_DWORD *)(v5 + 348),
&v19)) )
result = sub_550250(a4, &v13, &v10);
else
result = 0;
return result;
}
The ASM is probaly wrong, would something like this be close??
// Don't know what params goes where, ie: where the Vec3 goes and where the object goes
int __stdcall func_hook(param1, param2, param3, param4);
// Where to put the address? -->> 0x572EA0
// char __usercall sub_572EA0<al>(int a1<ecx>, int a2<edx>, int a3<eax>, int a4);
__declspec(naked) void func_hook()
{__asm{
push ebp
mov ebp, esp
mov ecx param1
mov edx param2
mov eax param3
push param4
call func_hook
leave
ret
}}
One thing missing in this piece of code is the address of the usercall (0x572EA0). Not sure where to put that...
This is how the program is calling the function. The call is at the bottom:
http://i43.tinypic.com/2mez9c8.jpg
that function you are hooking is Borland __fastcall, not __usercall (in fact there is actually no such convention, its just IDA's version of "unknown convention").
In terms of hooking this with inline asm, ECX, EDX and EAX are scratch registers, so we don't need to preserve them, and the call is well foermed so we don't need to worry about the stack:
static DWORD the_hook_address = 0x572EA0;
//init this somewhere with the correct (Base + RVA) address in case of module relocation (from ASLR etc.)
__declspec(naked) bool __stdcall the_hook(int a1, int a2, int a3, int a3)
{
__asm
{
MOV ECX,[ESP + 4]//a1
MOV EDX,[ESP + 8]//a2
MOV EAX,[ESP + 12]//a3
PUSH [ESP + 16]//a4
CALL the_hook_address
RETN 16 //4 * 4 args
}
}
I know the function takes an object as parameter and a *Vector3 as
parameter in which the calculated value will be stored. Is there an
easy way to tell which param will be what??
The 'easyness' depends on your experience in reverse engineering and with the program you are REing, in this case I'd say its a1, because you can see it move to a temporary, which is then accessed using pointer notation (IDA's way of representing unknown structs) to pull out 3 floats, which is generally what most apps use for vector components (and also most vectors have 3 components). It also helps greatly if you can actually debug the call in action, see what params are pointers, have a look at the functions call sites etc. For this reason I prefer using ollydbg for RE, supplementing it with IDA execution flow graphs for tricky jump sequences (think 20+ gotos in a function :<)
Related
I have a scenario where in some cases when opengl32.setPixelFormat is called it then call _wglDescribePixelFormat ( which is exported function ) which then calls further in the call stack ComputeBitsFromMasks and finally _MaskToBitsAndShift.
The _MaskToBitsAndShift function remains in the loop and never finishes, causing hanging the whole app. Callstack is
opengl32.dll!_MaskToBitsAndShift#12
opengl32.dll!ComputeBitsFromMasks
opengl32.dll!___wglGetBitfieldColorFormat#16
opengl32.dll!_InternalDescribePixelFormat#40
opengl32.dll!_wglDescribePixelFormat#16
opengl32.dll!_wglSetPixelFormat#12
gdi32full.dll!_SetPixelFormat#12
Unmanaged.dll!CGLContext::CreateOffScreenContext
Unmanaged.dll!Shared::Generate3DImages
Decoding the _MaskToBitsAndShift method from asm to c becomes like this.
Asm code
opengl32!MaskToBitsAndShift:
6da7d6f2 8bff mov edi,edi
6da7d6f4 55 push ebp
6da7d6f5 8bec mov ebp,esp
6da7d6f7 56 push esi
6da7d6f8 8b7508 mov esi,dword ptr [ebp+8]
6da7d6fb 33c0 xor eax,eax
6da7d6fd 40 inc eax – initialize eax to 1, used to find highest set bit in the mask
6da7d6fe c60200 mov byte ptr [edx],0
6da7d701 c60600 mov byte ptr [esi],0
6da7d704 84c8 test al,cl
6da7d706 7508 jne opengl32!MaskToBitsAndShift+0x1e (6da7d710)
6da7d708 03c0 add eax,eax – shifts eax (the bit) left
6da7d70a fe06 inc byte ptr [esi] – increases shift count
6da7d70c 85c1 test ecx,eax – ecx is the mask, first param to this function apparently
– and this is the problem. if ecx or mask is 0, test ecx,eax will never set the flag for je to fail, hence infinite loop
6da7d70e 74f8 je opengl32!MaskToBitsAndShift+0x16 (6da7d708)
6da7d710 5e pop esi
6da7d711 eb04 jmp opengl32!MaskToBitsAndShift+0x25 (6da7d717)
6da7d713 03c0 add eax,eax
6da7d715 fe02 inc byte ptr [edx]
6da7d717 85c1 test ecx,eax
6da7d719 75f8 jne opengl32!MaskToBitsAndShift+0x21 (6da7d713)
6da7d71b 5d pop ebp
6da7d71c c20400 ret 4
Equivalant c++ code
void stdcall MaskToBitsAndShift(DWORD mask, BYTE* shiftCount, BYTE* bitCount)
{
// literal translation from asm; could be safer using bittest intrinsics or counted bits but no big deal
DWORD bit = 1;
*shiftCount = 0;
*bitCount = 0;
while (!(mask & bit))
{ *shiftCount += 1; bit <<= 1; }
while (mask & bit)
{ *bitCount += 1; bit <<= 1; }
}
If we notice the mask if 0, the loop will never end.
I cannot hook this function because it is not exported.
Any idea about working around it ? or rewriting the _wglDescribePixelFormat method which is exported but I have no idea how to tranlate that.
The initial call to the setPixelFormat is
bool CGLContext::CreateOffScreenContext(int nWidth, int nHeight, CString* pstrLog /*=NULL*/)
{
if(pstrLog)
pstrLog->Append("Creating Off Screen Context\r\n");
m_eContextType = CONTEXT_TYPE_OFFSCREEN;
// Create a new Device Context
m_pDC = new CDC;
m_pDC->CreateCompatibleDC(NULL);
// Initialize all of the compenents used to select a pixel format
memset(&m_PixelFormatDescriptor, 0, sizeof(m_PixelFormatDescriptor));
m_PixelFormatDescriptor.nSize = sizeof(PIXELFORMATDESCRIPTOR);
m_PixelFormatDescriptor.nVersion = 1;
m_PixelFormatDescriptor.dwFlags = PFD_DRAW_TO_BITMAP|PFD_SUPPORT_OPENGL|PFD_SUPPORT_GDI;
m_PixelFormatDescriptor.iPixelType = PFD_TYPE_RGBA;
m_PixelFormatDescriptor.cColorBits = 0;
m_PixelFormatDescriptor.cDepthBits = 0;
m_PixelFormatDescriptor.cAccumBits = 0;
m_PixelFormatDescriptor.cStencilBits = 0;
m_PixelFormatDescriptor.cAuxBuffers = 0;
m_PixelFormatDescriptor.iLayerType = PFD_MAIN_PLANE;
m_hDC = m_pDC->m_hDC;
int nPixelFormat = ChoosePixelFormat(m_hDC, &m_PixelFormatDescriptor);
if(nPixelFormat == 0) {
if(pstrLog)
{
CString str;
str.Format("Unable to Choose Pixel Format: %li\r\n", nPixelFormat);
pstrLog->Append(str);
pstrLog->Append(DescribePFD(m_PixelFormatDescriptor));
return false;
}
else
{
ThrowException("Unable to Choose Pixel Format");
}
}.....
I need to port an old project to the latest visual studio but it has some very awful code in it that I don't know how to resolve.
if have this function:
void CBuffer::AddData( LPBYTE lpData, u_long uDataSize, u_long &uRemnant )
{
int cb;
LPBYTE ptr = GetWritableBuffer( (int *)&cb );
cb = ( cb < uRemnant? cb: uRemnant );
ASSERT( ptr + cb <= m_lpBufMax );
memcpy( (void*)ptr, &lpData[uDataSize - uRemnant], cb );
m_pTail = ptr + cb;
uRemnant -= cb;
}
which prompts
buffer.cpp(90): warning C4458: declaration of 'cb' hides class member
here int cb overwrite u_long cb defined by the class CBuffer.
Is there a way to tell which cb should be used after this?
LPBYTE ptr = GetWritableBuffer( (int *)&cb );
Local variables always shadow class member variables or global variables. So, in this method, always the local variable int cb is used.
My program was killed when the function "dbmSetIndex" was returned.
You can see the killed position below. (=> part)
Could you explain what happened?
(x86 intel)
0x0000000000420723 <+83>: mov rdi,r14
0x0000000000420726 <+86>: call 0x405260 <dbmSetIndex#plt>
0x000000000042072b <+91>: test eax,eax
0x000000000042072d <+93>: mov ebp,eax
=> 0x000000000042072f <+95>: mov DWORD PTR [r12],eax
0x0000000000420733 <+99>: jne 0x4207d0 <FnDBBase::SelectSecurity(s_oms_security*, char*)+256>
0x0000000000420739 <+105>: lea rsi,[rip+0x4197d] # 0x4620bd
Here is the dbmSetIndex code.
I can't find what part of this code caused this problem.
int dbmSetIndex ( dbmHandle* aHandle, const char* aTable, const char* aIndexName )
{
dbmInternalHandle* pHandle = NULL;
_TRY
{
pHandle = (dbmInternalHandle*)aHandle->mHandle;
// Water Mark가 다르면 걍 리턴해라.
if ( unlikely ( aHandle->mMark != DBM_HANDLE_MARK ) )
{
DBM_ERR ( "invalide magic number (%ld)", aHandle->mMark );
_THROW( ERR_DBM_INVALID_HANDLE );
}
if( pHandle->mRemote != NULL )
{
if( pHandle->mRemote->mSockFd > 0 )
{
_CALL( dbmRemoteSetIndex( aHandle, aTable, aIndexName ) );
_RETURN;
}
}
/****************************************
* DataObject 맵핑.
****************************************/
memset_s( &pHandle->mData, 0x00, sizeof( pHandle->mData ) );
memcpy_s ( pHandle->mData.mTableName, aTable, strlen_s ( aTable ) + 1 );
pHandle->mData.mTransType = DBM_SET_INDEX;
pHandle->mData.mUserData = (char*)aIndexName;
/****************************************
* mAct 호출.
****************************************/
_CALL( pHandle->mTrans->mAct ( pHandle ) );
}
_CATCH
{
_CATCH_ERR;
}
_FINALLY
_END
}
You provided a little bit of dissassembly which shows that the call to the function you provided returned already. The crash did not occur within the function, but afterwards:
Call of your function:
0x0000000000420726 <+86>: call 0x405260 <dbmSetIndex#plt>
Here you returned already:
0x000000000042072b <+91>: test eax,eax
The critical line is a memory access to the address stored in register r12 (write):
0x000000000042072f <+95>: mov DWORD PTR [r12],eax
Let your debugger show the registers and have a look at the content of r12. It is very likely that it is 0x0000000000000000 or a small value, thus a null pointer (or null reference), but it could contain, too, an invalid address (uninitialised pointer!).
There is little more left to tell from the information you provide, though. You will have to look at the code location where the function is called -- it must be within function FnDBBase::SelectSecurity(s_oms_security*, char*) because you jump (jne) to an offset within this function ([...] + 256). There should be an if involved (test + jne instructions) and probably some pointer assignment. Possibly something like this:
SomeClass* s = [...];
s->someMember = dbmSetIndex([...]); // (*)
if(*s->someMember)
(*): Failure location, error happened during assignment after the function completed already. Don't count 100% on finding such an assignment, it could be, too, a call to an inlined setter function.
And here we see, too, why r12 is not necessarily 0: it would contain the precalculated offset of someMember within SomeClass, i. e. &(s->someMember) which could well be, if s is 0, e. g. 16, 28, ... Precisely, the value contained then is equal to offsetof(SomeClass, somemember).
I am writing a code for thread handling in C++. One instance of a Thread has a pointer to PCB structure and in the constructor of the Thread I just call myPCB = new PCB(name, stackSize, timeSlice, this). It was all working just fine until I tried to make an array of pointers to Thread.
When I just make a pointer to thread and initialized it with new Thread(name, stackSize, timeSlice) the name in PCB of that Thread is appointed correctly.
But when I try it with an array of pointers all the PCBs have the same value for name variable.
I have checked and they are all diffrent PCBs (their IDs are diffrent). Their names get properly initialized in the constructor, but somewhere between the end of the constructor of the Nth and the end of the (N+1)th all names get the same value, that of N+1.
PCB constructor:
PCB::PCB(TName namee, StackSize stackSizee, Time timeSlicee,Thread *threadd){
status = begging;
id = genID++;
if(namee) name = namee;
else name = "Thread"+id;
createStack(stackSizee);
thread = threadd;
timeSlice = timeSlicee;
System::numberOfThreads++;
System::allPCBQueue.add(this);
waitingMe = new Queue();
waitingFor = 0;
semaphore = 0;
sleepTime = -1;
}
void PCB::createStack(StackSize stackSize){
intOff;
if(stackSize > maxStack) stack = new char[maxStack];
else stack = new char[stackSize];
newSS = FP_SEG(stack + stackSize);
newSP = FP_OFF(stack + stackSize);
asm{
mov oldSS, ss
mov oldSP, sp
mov ss, newSS
mov sp, newSP
push ax; push bx; push cx; push dx; push es; push ds; push si; push di; push bp
mov newSP, sp
mov newSS, ss
mov sp, oldSP
mov ss, oldSS
}
stackPointer = MK_FP(newSS, newSP);
intOn;
}
I figure its something with createStack() but I don't know what. All help is appreciated.
*Note: I currently don't have constant access to the internet so please don't get angry if I don't reply fastly. I will try to check on this question as much as I can.
EDITED:
PCB class definition:
class PCB
{
static ID genID;
char *stack;
void *stackPointer;
Thread *thread;
TName name;
ID id;
Time timeSlice, sleepTime;
Status status;
Queue *waitingMe;
PCB* waitingFor;
KernelSem* semaphore;
friend class Thread;
// static unsigned newSS, newSP, oldSS, oldSP;
public:
static StackSize maxStack;
PCB(TName name, StackSize stackSize, Time timeSlice,Thread *thread);
~PCB(void);
void runThread();
ID getID(){
return id;
}
TName getName(){
return name;
}
void setStatus(Status status){
this->status = status;
}
Status getStatus(){
return status;
}
int getEnding(){
if(status == ending) return 1;
return 0;
}
int getBegging(){
if(status == begging) return 1;
return 0;
}
void createStack(StackSize stackSize);
void* getStackPointer(){
return stackPointer;
}
void setStack(void *newStackPointer){
stackPointer = newStackPointer;
}
Time getTimeSlice(){return timeSlice;}
Time getSleepTime(){return sleepTime;}
void decrementSleepTime(){sleepTime--;}
void setSemaphore(KernelSem* kersem){this->semaphore = kersem;}
void resetSemphore(){this->semaphore = 0;}
Thread* getThread(){return thread;}
};
Code where this happens:
Producer **pro = new Producer*[N];
for (i=0; i<N; i++){
producerName[8]='0'+i;
pro[i] = new Producer(buff, producerName ,'0'+i, TIME_SLICE);
pro[i]->start();
}
It's the part of a test file that I got with this assignment. It mustn't be changed. But it is regular.
I have put
allPCBQueue->listAll()
after
pro[i] = new Producer(buff, producerName ,'0'+i, TIME_SLICE);
and I always get that all of the names are same. allPCBQueue is a simple list of PCBs
if(namee) name = namee;
else name = "Thread"+id; <<< Doesn't do what you think it does.
"Thread" is a char *, adding a number to it will give you the pointer + offset.
You don't want to SWITCH to your new stack until AFTER you have created it. Instead of using push to store, just use something like this:
stackPointer = MK_FP(newSS, newSP);
unsigned *sp = reinterpret_cast<unsigned *>(stackPointer);
*--sp = 0; // AX
*--sp = 0; // BX
*--sp = 0; // CX
*--sp = 0; // DX
*--sp = default_ds; // You'll have to dig this out with some inline assembler
*--sp = default_es; // You'll have to dig this out with some inline assembler
*--sp = 0; // SI
*--sp = 0; // DI
*--sp = 0; // BP
stackPointer = reinterpret_cast<void *>(sp);
[Of course, it would be easier to just make stackpointer a pointer to int in the first place].
Since the thread is starting from scratch, values of AX, BX, etc, doesn't matter. ES/DS may matter depending on what memory model you are using. Not pushing onto the stack also means you don't have to disable interrupts for this part - always a bonus.
Unfortunately, your code isn't showing what you are doing with "array of PCB's", so I can't say what' wrong there. And I'm sure someone says this should be a comment, not an answer, since it doesn't actually answer your question - but formatting code in comments is nearly hopeless...
Edit:
I'm guessing that "producername" is a local variable in your code that creates the threads. This won't work, but I think it's a bit difficult to dictate that the caller must ensure that the name stays forever, so I think what you should do is:
if(namee)
{
size_t len = strlen(namee);
char *name_buf = new char[len+1];
strcpy(name_buf, namee);
name = name_buf;
}
else
{
// Make up some random name here.
}
The code was
name = namee
or
this->name = namee
I just made it
strcpy(name, namee)
and it works now.
I think I'm making just a fundamental mistake, but I cannot for the life of me see it.
I'm calling a method on an Objective-C object from within a C++ class (which is locked). I'm using NSInvocation to prevent me from having to write hundreds methods just to access the data in this other object.
These are the steps I'm going through. This is my first call, and I want to pass s2. I can't really provide a compilable example, but hopefully it's just a DUHRRRRR problem on my part.
float s2[3];
id args2s[] = {(id)&_start.x(),(id)&_start.y(),(id)&s2};
_view->_callPixMethod(#selector(convertPixX:pixY:toDICOMCoords:),3,args2s);
This is the View method being called
invokeUnion View::_callPixMethod(SEL method, int nArgs, id args[])
{
DataModule* data;
DataVisitor getdata(&data);
getConfig()->accept(getdata);
invokeUnion retVal;
retVal.OBJC_ID = data->callPixMethod(_index, _datasetKey, method, nArgs, args);
return retVal;
}
Invoke Union is a union so I can get the float value returned by NSInvocation.
union invokeUnion {
id OBJC_ID;
int intValue;
float floatValue;
bool boolValue;
};
This is the method in the data Object (pthread locked with lock() and unlock());
id DataModule::callPixMethod(int index, std::string predicate, SEL method, int nArgs, id args[] )
{
// May Block
DCMPix *pix =[[getSeriesData(predicate) pix] objectAtIndex:index];
lock();
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSMethodSignature *signature;
NSInvocation *invocation;
signature = [DCMPix instanceMethodSignatureForSelector:method];
invocation = [NSInvocation invocationWithMethodSignature:signature];
[invocation setSelector:method];
[invocation setTarget:pix];
if (nArgs > 0) for (int n = 0; n < nArgs; n++) {
SFLog(#"invocation: i=%d, *ptr=0x%x, valf=%f, vald=%d",n,args[n],*args[n],*args[n]);
[invocation setArgument:args[n] atIndex:2+n];
}
id retVal;
[invocation invoke];
[invocation getReturnValue:&retVal];
[pool release];
unlock();
return retVal;
}
The method in the DCMPix object (which I can't modify, it's part of a library) is the following:
-(void) convertPixX: (float) x pixY: (float) y toDICOMCoords: (float*) d pixelCenter: (BOOL) pixelCenter
{
if( pixelCenter)
{
x -= 0.5;
y -= 0.5;
}
d[0] = originX + y*orientation[3]*pixelSpacingY + x*orientation[0]*pixelSpacingX;
d[1] = originY + y*orientation[4]*pixelSpacingY + x*orientation[1]*pixelSpacingX;
d[2] = originZ + y*orientation[5]*pixelSpacingY + x*orientation[2]*pixelSpacingX;
}
-(void) convertPixX: (float) x pixY: (float) y toDICOMCoords: (float*) d
{
[self convertPixX: x pixY: y toDICOMCoords: d pixelCenter: YES];
}
It's crashing when it tries to access d[0]. BAD_EXC_ACCESS which I know means it's accessing released memory, or memory outside of it's scope.
I'm getting lost keeping track of my pointers to pointers. the two float values come across fine (as does other info in other methods) but this is the only one asking for a float* as a parameter. From what I understand the convertPixX: method was converted over from a C program written for Mac OS 9... which is why it asks for the c-array as an out value... I think.
Anyway, any insight would be greatly appreciated.
I've tried sending the value like this:
float *s2 = new float[3];
void* ps2 = &s2;
id args2s[] = {(id)&_start.x(),(id)&_start.y(),(id)&ps2};
_view->_callPixMethod(#selector(convertPixX:pixY:toDICOMCoords:),3,args2s);
But that gives a SIGKILL - plus I'm sure it's bogus and wrong. ... but I tried.
anyway... pointers! cross-language! argh!
Thanks,
An array is not a pointer. Try adding the following line
NSLog(#"%p, %p", s2, &s2);
just above.
id args2s[] = {(id)&_start.x(),(id)&_start.y(),(id)&s2};
s2 and &s2 are both the address of the first float in your array, so when you do:
[invocation setArgument:args[n] atIndex:2+n];
for n = 2, you are not copying in a pointer to the first float, but the first float, possibly the first two floats if an id is 64 bits wide.
Edit:
To fix the issue, this might work (not tested).
float s2[3];
float* s2Pointer = s2;
id args2s[] = {(id)&_start.x(),(id)&_start.y(),(id)&s2Pointer};
_view->_callPixMethod(#selector(convertPixX:pixY:toDICOMCoords:),3,args2s);
s2Pointer is a real pointer that will give you the double indirection you need.