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).
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.
Here's the code below.
void SignalView::OnFilePrintPreview()
{
if(RcursorPosX-LcursorPosX<=0){
AfxMessageBox(_T("Please set cursor positions.\nYou can only print out the area between left and right cursors"));
return;
}
CScrollView::OnFilePrintPreview();
}
BOOL SignalView::OnPreparePrinting(CPrintInfo* pInfo)
{
if(RcursorPosX-LcursorPosX>100*4*2)
RcursorPosX = LcursorPosX+100*4*2; //800 = 100 cursor x 4(gridX) x 2(zoomX)
pInfo->SetMinPage(1);
pInfo->SetMaxPage(1);
return DoPreparePrinting(pInfo); //<===========
}
void SignalView::OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo)
{
PRINTDLG* pPrintDlg = new PRINTDLG;
AfxGetApp()->GetPrinterDeviceDefaults(pPrintDlg);
DEVMODE* lpDevMode = (DEVMODE*)::GlobalLock(pPrintDlg->hDevMode);
lpDevMode->dmOrientation = DMORIENT_LANDSCAPE;
while(!pDC->ResetDC(lpDevMode));
::GlobalUnlock(pPrintDlg->hDevMode);
delete pPrintDlg;
}
I'm trying to use print functions. But I remade it because I deleted it and made a new class again which is derived from CScrollView, so I don't use the original view that was made from the beginning.
And now, I achieved what I want but the problem is that an error happens when I try to call and close print event OnFilePrintPreview() around 30-40 times, then it would shut down with an error message 0xC0000005.
And it happens from the function DoPreparePrinting(pInfo), and then it goes to COMMDLG_AFXCTXFUNC(BOOL ,PrintDlgW,(LPPRINTDLGW unnamed1),(unnamed1)) in afxcomctl32.inl file and then it provokes an error message.
Why does this problem happen? And does the code seem to go the right direction?
P.S.
The error happens this part in disassembly mode.
COMMDLG_AFXCTXFUNC(BOOL ,PrintDlgW,(LPPRINTDLGW unnamed1),(unnamed1))
7824CD80 mov edi,edi
7824CD82 push ebp
7824CD83 mov ebp,esp
7824CD85 mov eax,dword ptr [unnamed1]
7824CD88 push eax
7824CD89 call AfxGetModuleState (780F3320h)
7824CD8E mov ecx,dword ptr [eax+94h]
7824CD94 mov ecx,dword ptr [ecx+4]
7824CD97 call CCommDlgWrapper::_PrintDlgW (7824CDB0h)
7824CD9C pop ebp //<======= it's stopped at this point.
7824CD9D ret 4
while(!pDC->ResetDC(lpDevMode));
::GlobalUnlock(pPrintDlg->hDevMode);
This looks like trouble. If loop condition is true the first time and the second time, then there is no guarantee that it will eventually stop.
The following may not be the cause of your error, but you should try to follow these procedures in general.
When declaring new variables set them to zero, so all structure members are zero:
PRINTDLG* pPrintDlg = new PRINTDLG;
memset(pPrintDlg, 0, sizeof(pPrintDlg));
Some structures require to know the size. This has to do with Microsoft version control:
pPrintDlg->lStructSize = sizeof(PRINTDLG);
In this case you don't need to use new to allocate pPrintDlg (but it won't cause problems if you do)
You should be able to intercept the request for printing (before printer device context is created) and change to landscape mode, so Print dialog box is shown in landscape mode.
void SignalView::OnFilePrint()
{
PRINTDLG printDlg = { 0 };
printDlg.lStructSize = sizeof(PRINTDLG);
if (AfxGetApp()->GetPrinterDeviceDefaults(&printDlg))
{
if (printDlg.hDevMode)
{
DEVMODE *dm = (DEVMODE*)::GlobalLock(printDlg.hDevMode);
if (dm)
{
dm->dmFields |= DM_ORIENTATION;
dm->dmOrientation = DMORIENT_LANDSCAPE;
::GlobalUnlock(printDlg.hDevMode);
}
}
}
CScrollView::OnFilePrint();
}
Message map should look like this:
BEGIN_MESSAGE_MAP(SignalView, CScrollView)
ON_COMMAND(ID_FILE_PRINT, OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_DIRECT, OnFilePrint)
//**************************************************
ON_COMMAND(ID_FILE_PRINT_PREVIEW, OnFilePrintPreview)
//**************************************************
END_MESSAGE_MAP()
User can change the print mode back to portrait in print dialog box. You can repeat the same code in OnBeginPrinting if you want to force landscape.
Is there software smart enough to figure out that you got a pointer from somewhere and the returned pointer could be NULL and no where in the block do you do:
ptr = getSomeDataThatCouldReturnNULLAt(-1);
...
if(ptr)
{
//code
}
or
if(!ptr)
{
return;
}
Is there software that can let you know all the places where this might not be checked?
Thanks
Checking for runtime problems.
the better way to code this would be as follows :
s32 getSomeDataThatCouldReturnNULLAt( s32 intParam, void **inputPointer);
and then in your function where you want to invoke this function :
s32 returnValue = 0 ;
void * ptr = NULL ;
if((returnValue = getSomeDataThatCouldReturnNULLAt( -1, &ptr) ) != ERROR ||
ptr ==NULL )
return returnValue;
returnValue can indicate the error that occured in your getSomeDataThatCouldReturnNULLAt
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 :<)