I have been trying for awhile to get a correct vtable order for direct2d and I thought I got the correct one but it has not been working other then the first 3 (IUnknown inherited), and i was wondering how to get a proper vtable order.
My vtable so far
;ID2D1RenderTargetVtbl
ID2D1RenderTarget_QueryInterface textequ <qword ptr [rbx+0]>
ID2D1RenderTarget_AddRef textequ <qword ptr [rbx+8]>
ID2D1RenderTarget_Release textequ <qword ptr [rbx+16]>
ID2D1RenderTarget_GetFactory textequ <qword ptr [rbx+24]>
ID2D1RenderTarget_BeginDraw textequ <qword ptr [rbx+32]>
ID2D1RenderTarget_Clear textequ <qword ptr [rbx+40]>
ID2D1RenderTarget_CreateBitmap textequ <qword ptr [rbx+48]>
ID2D1RenderTarget_CreateBitmapBrush textequ <qword ptr [rbx+56]>
ID2D1RenderTarget_CreateBitmapFromWicBitmap textequ <qword ptr [rbx+64]>
ID2D1RenderTarget_CreateCompatibleRenderTarget textequ <qword ptr [rbx+72]>
ID2D1RenderTarget_CreateGradientStopCollection textequ <qword ptr [rbx+80]>
ID2D1RenderTarget_CreateLayer textequ <qword ptr [rbx+88]>
ID2D1RenderTarget_CreateLinearGradientBrush textequ <qword ptr [rbx+96]>
ID2D1RenderTarget_CreateMesh textequ <qword ptr [rbx+104]>
ID2D1RenderTarget_CreateRadialGradientBrush textequ <qword ptr [rbx+112]>
ID2D1RenderTarget_CreateSharedBitmap textequ <qword ptr [rbx+120]>
ID2D1RenderTarget_CreateSolidColorBrush textequ <qword ptr [rbx+128]>
ID2D1RenderTarget_DrawBitmap textequ <qword ptr [rbx+136]>
ID2D1RenderTarget_DrawEllipse textequ <qword ptr [rbx+144]>
ID2D1RenderTarget_DrawGeometry textequ <qword ptr [rbx+152]>
ID2D1RenderTarget_DrawGlyphRun textequ <qword ptr [rbx+160]>
ID2D1RenderTarget_DrawLine textequ <qword ptr [rbx+168]>
ID2D1RenderTarget_DrawRectangle textequ <qword ptr [rbx+176]>
ID2D1RenderTarget_DrawRoundedRectangle textequ <qword ptr [rbx+184]>
ID2D1RenderTarget_DrawText textequ <qword ptr [rbx+192]>
ID2D1RenderTarget_DrawTextLayout textequ <qword ptr [rbx+200]>
ID2D1RenderTarget_EndDraw textequ <qword ptr [rbx+208]>
ID2D1RenderTarget_FillEllipse textequ <qword ptr [rbx+216]>
ID2D1RenderTarget_FillGeometry textequ <qword ptr [rbx+224]>
ID2D1RenderTarget_FillMesh textequ <qword ptr [rbx+232]>
ID2D1RenderTarget_FillOpacityMask textequ <qword ptr [rbx+240]>
ID2D1RenderTarget_FillRectangle textequ <qword ptr [rbx+248]>
ID2D1RenderTarget_FillRoundedRectangle textequ <qword ptr [rbx+256]>
ID2D1RenderTarget_Flush textequ <qword ptr [rbx+264]>
ID2D1RenderTarget_GetAntialiasMode textequ <qword ptr [rbx+272]>
ID2D1RenderTarget_GetDpi textequ <qword ptr [rbx+280]>
ID2D1RenderTarget_GetMaximumBitmapSize textequ <qword ptr [rbx+288]>
ID2D1RenderTarget_GetPixelFormat textequ <qword ptr [rbx+296]>
ID2D1RenderTarget_GetPixelSize textequ <qword ptr [rbx+304]>
ID2D1RenderTarget_GetSize textequ <qword ptr [rbx+312]>
ID2D1RenderTarget_GetTags textequ <qword ptr [rbx+320]>
ID2D1RenderTarget_GetTextAntialiasMode textequ <qword ptr [rbx+328]>
ID2D1RenderTarget_GetTextRenderingParams textequ <qword ptr [rbx+336]>
ID2D1RenderTarget_GetTransform textequ <qword ptr [rbx+344]>
ID2D1RenderTarget_IsSupported textequ <qword ptr [rbx+352]>
ID2D1RenderTarget_PopAxisAlignedClip textequ <qword ptr [rbx+360]>
ID2D1RenderTarget_PopLayer textequ <qword ptr [rbx+368]>
ID2D1RenderTarget_PushAxisAlignedClip textequ <qword ptr [rbx+376]>
ID2D1RenderTarget_PushLayer textequ <qword ptr [rbx+384]>
ID2D1RenderTarget_RestoreDrawingState textequ <qword ptr [rbx+392]>
ID2D1RenderTarget_SaveDrawingState textequ <qword ptr [rbx+400]>
ID2D1RenderTarget_SetAntialiasMode textequ <qword ptr [rbx+408]>
ID2D1RenderTarget_SetDpi textequ <qword ptr [rbx+416]>
ID2D1RenderTarget_SetTags textequ <qword ptr [rbx+424]>
ID2D1RenderTarget_SetTextAntialiasMode textequ <qword ptr [rbx+432]>
ID2D1RenderTarget_SetTextRenderingParams textequ <qword ptr [rbx+440]>
ID2D1RenderTarget_SetTransform textequ <qword ptr [rbx+448]>
;ID2D1Factory
ID2D1Factory_QueryInterface textequ <qword ptr [rbx+0]>
ID2D1Factory_AddRef textequ <qword ptr [rbx+8]>
ID2D1Factory_Release textequ <qword ptr [rbx+16]>
ID2D1Factory_CreateDCRenderTarget textequ <qword ptr [rbx+24]>
ID2D1Factory_CreateDrawingStateBlock textequ <qword ptr [rbx+32]>
ID2D1Factory_CreateDxgiSurfaceRenderTarget textequ <qword ptr [rbx+40]>
ID2D1Factory_CreateEllipseGeometry textequ <qword ptr [rbx+48]>
ID2D1Factory_CreateGeometryGroup textequ <qword ptr [rbx+56]>
ID2D1Factory_CreateHwndRenderTarget textequ <qword ptr [rbx+64]>
ID2D1Factory_CreatePathGeometry textequ <qword ptr [rbx+72]>
ID2D1Factory_CreateRectangleGeometry textequ <qword ptr [rbx+80]>
ID2D1Factory_CreateRoundedRectangleGeometry textequ <qword ptr [rbx+88]>
ID2D1Factory_CreateStrokeStyle textequ <qword ptr [rbx+96]>
ID2D1Factory_CreateTransformedGeometry textequ <qword ptr [rbx+104]>
ID2D1Factory_CreateWicBitmapRenderTarget textequ <qword ptr [rbx+112]>
ID2D1Factory_GetDesktopDpi textequ <qword ptr [rbx+120]>
ID2D1Factory_ReloadSystemMetrics textequ <qword ptr [rbx+128]>
;dcrendertarget
ID2D1DCRenderTarget_BeginDraw textequ <qword ptr [rbx+24]>
ID2D1DCRenderTarget_Clear textequ <qword ptr [rbx+32]>
ID2D1DCRenderTarget_CreateBitmap textequ <qword ptr [rbx+40]>
ID2D1DCRenderTarget_CreateBitmapBrush textequ <qword ptr [rbx+48]>
ID2D1DCRenderTarget_CreateBitmapFromWicBitmap textequ <qword ptr [rbx+56]>
ID2D1DCRenderTarget_CreateCompatibleRenderTarget textequ <qword ptr [rbx+64]>
ID2D1DCRenderTarget_CreateGradientStopCollection textequ <qword ptr [rbx+72]>
ID2D1DCRenderTarget_CreateLayer textequ <qword ptr [rbx+80]>
ID2D1DCRenderTarget_CreateLinearGradientBrush textequ <qword ptr [rbx+88]>
ID2D1DCRenderTarget_CreateMesh textequ <qword ptr [rbx+96]>
ID2D1DCRenderTarget_CreateRadialGradientBrush textequ <qword ptr [rbx+104]>
ID2D1DCRenderTarget_CreateSharedBitmap textequ <qword ptr [rbx+112]>
ID2D1DCRenderTarget_CreateSolidColorBrush textequ <qword ptr [rbx+120]>
ID2D1DCRenderTarget_DrawBitmap textequ <qword ptr [rbx+128]>
ID2D1DCRenderTarget_DrawEllipse textequ <qword ptr [rbx+136]>
ID2D1DCRenderTarget_DrawGeometry textequ <qword ptr [rbx+144]>
ID2D1DCRenderTarget_DrawGlyphRun textequ <qword ptr [rbx+152]>
ID2D1DCRenderTarget_DrawLine textequ <qword ptr [rbx+160]>
ID2D1DCRenderTarget_DrawRectangle textequ <qword ptr [rbx+168]>
ID2D1DCRenderTarget_DrawRoundedRectangle textequ <qword ptr [rbx+176]>
ID2D1DCRenderTarget_DrawText textequ <qword ptr [rbx+184]>
ID2D1DCRenderTarget_DrawTextLayout textequ <qword ptr [rbx+192]>
ID2D1DCRenderTarget_EndDraw textequ <qword ptr [rbx+200]>
ID2D1DCRenderTarget_FillEllipse textequ <qword ptr [rbx+208]>
ID2D1DCRenderTarget_FillGeometry textequ <qword ptr [rbx+216]>
ID2D1DCRenderTarget_FillMesh textequ <qword ptr [rbx+224]>
ID2D1DCRenderTarget_FillOpacityMask textequ <qword ptr [rbx+232]>
ID2D1DCRenderTarget_FillRectangle textequ <qword ptr [rbx+240]>
ID2D1DCRenderTarget_FillRoundedRectangle textequ <qword ptr [rbx+248]>
ID2D1DCRenderTarget_Flush textequ <qword ptr [rbx+256]>
ID2D1DCRenderTarget_GetAntialiasMode textequ <qword ptr [rbx+264]>
ID2D1DCRenderTarget_GetDpi textequ <qword ptr [rbx+272]>
ID2D1DCRenderTarget_GetMaximumBitmapSize textequ <qword ptr [rbx+280]>
ID2D1DCRenderTarget_GetPixelFormat textequ <qword ptr [rbx+288]>
ID2D1DCRenderTarget_GetPixelSize textequ <qword ptr [rbx+296]>
ID2D1DCRenderTarget_GetSize textequ <qword ptr [rbx+304]>
ID2D1DCRenderTarget_GetTags textequ <qword ptr [rbx+312]>
ID2D1DCRenderTarget_GetTextAntialiasMode textequ <qword ptr [rbx+320]>
ID2D1DCRenderTarget_GetTextRenderingParams textequ <qword ptr [rbx+328]>
ID2D1DCRenderTarget_GetTransform textequ <qword ptr [rbx+336]>
ID2D1DCRenderTarget_IsSupported textequ <qword ptr [rbx+344]>
ID2D1DCRenderTarget_PopAxisAlignedClip textequ <qword ptr [rbx+352]>
ID2D1DCRenderTarget_PopLayer textequ <qword ptr [rbx+360]>
ID2D1DCRenderTarget_PushAxisAlignedClip textequ <qword ptr [rbx+368]>
ID2D1DCRenderTarget_PushLayer textequ <qword ptr [rbx+376]>
ID2D1DCRenderTarget_RestoreDrawingState textequ <qword ptr [rbx+384]>
ID2D1DCRenderTarget_SaveDrawingState textequ <qword ptr [rbx+392]>
ID2D1DCRenderTarget_SetAntialiasMode textequ <qword ptr [rbx+400]>
ID2D1DCRenderTarget_SetDpi textequ <qword ptr [rbx+408]>
ID2D1DCRenderTarget_SetTags textequ <qword ptr [rbx+416]>
ID2D1DCRenderTarget_SetTextAntialiasMode textequ <qword ptr [rbx+424]>
ID2D1DCRenderTarget_SetTextRenderingParams textequ <qword ptr [rbx+432]>
ID2D1DCRenderTarget_SetTransform textequ <qword ptr [rbx+440]>
ID2D1DCRenderTarget_BindDC textequ <qword ptr [rbx+448]>
I know addref works but i have not gotten CreateDCRenderTarget to work at all
A source for how i got these can be found here VTable, but now i'm doubting that it actually works
So if anybody knows how to get the correct VTable order That would be amazing.
The order of the vtable is wrong. Taken from DirectXVtable it defines the Vtable then defines it again but in the wrong order.
#define INTERFACE ID2D1Factory
DECLARE_INTERFACE_(ID2D1Factory, IUnknown)
{
BEGIN_INTERFACE
/* IUnknown methods */
STDMETHOD(QueryInterface)(THIS_ REFIID riid, void **ppvObject) PURE;
STDMETHOD_(ULONG, AddRef)(THIS) PURE;
STDMETHOD_(ULONG, Release)(THIS) PURE;
/* ID2D1Factory methods */
STDMETHOD(ReloadSystemMetrics)(THIS) PURE;
STDMETHOD_(void, GetDesktopDpi)(THIS_ FLOAT *dpiX, FLOAT *dpiY) PURE;
STDMETHOD(CreateRectangleGeometry)(THIS_ D2D1_RECT_F *rectangle, ID2D1RectangleGeometry **rectangleGeometry) PURE;
STDMETHOD(CreateRoundedRectangleGeometry)(THIS_ D2D1_ROUNDED_RECT *roundedRectangle, ID2D1RoundedRectangleGeometry **roundedRectangleGeometry) PURE;
STDMETHOD(CreateEllipseGeometry)(THIS_ D2D1_ELLIPSE *ellipse, ID2D1EllipseGeometry **ellipseGeometry) PURE;
STDMETHOD(CreateGeometryGroup)(THIS_ D2D1_FILL_MODE fillMode, ID2D1Geometry **geometries, UINT geometriesCount, ID2D1GeometryGroup **geometryGroup) PURE;
STDMETHOD(CreateTransformedGeometry)(THIS_ ID2D1Geometry *sourceGeometry, D2D1_MATRIX_3X2_F *transform, ID2D1TransformedGeometry **transformedGeometry) PURE;
STDMETHOD(CreatePathGeometry)(THIS_ ID2D1PathGeometry **pathGeometry) PURE;
STDMETHOD(CreateStrokeStyle)(THIS_ D2D1_STROKE_STYLE_PROPERTIES *strokeStyleProperties, FLOAT *dashes, UINT dashesCount, ID2D1StrokeStyle **strokeStyle) PURE;
STDMETHOD(CreateDrawingStateBlock)(THIS_ D2D1_DRAWING_STATE_DESCRIPTION *drawingStateDescription, IDWriteRenderingParams *textRenderingParams, ID2D1DrawingStateBlock **drawingStateBlock) PURE;
STDMETHOD(CreateWicBitmapRenderTarget)(THIS_ IWICBitmap *target, D2D1_RENDER_TARGET_PROPERTIES *renderTargetProperties, ID2D1RenderTarget **renderTarget) PURE;
STDMETHOD(CreateHwndRenderTarget)(THIS_ D2D1_RENDER_TARGET_PROPERTIES *renderTargetProperties, D2D1_HWND_RENDER_TARGET_PROPERTIES *hwndRenderTargetProperties, ID2D1HwndRenderTarget **hwndRenderTarget) PURE;
STDMETHOD(CreateDxgiSurfaceRenderTarget)(THIS_ IDXGISurface *dxgiSurface, D2D1_RENDER_TARGET_PROPERTIES *renderTargetProperties, ID2D1RenderTarget **renderTarget) PURE;
STDMETHOD(CreateDCRenderTarget)(THIS_ D2D1_RENDER_TARGET_PROPERTIES *renderTargetProperties, ID2D1DCRenderTarget **dcRenderTarget) PURE;
END_INTERFACE
};
#undef INTERFACE
#define ID2D1Factory_QueryInterface(this,A,B) (this)->lpVtbl->QueryInterface(this,A,B)
#define ID2D1Factory_AddRef(this) (this)->lpVtbl->AddRef(this)
#define ID2D1Factory_Release(this) (this)->lpVtbl->Release(this)
#define ID2D1Factory_CreateDCRenderTarget(this,A,B) (this)->lpVtbl->CreateDCRenderTarget(this,A,B)
#define ID2D1Factory_CreateDrawingStateBlock(this,A,B,C) (this)->lpVtbl->CreateDrawingStateBlock(this,A,B,C)
#define ID2D1Factory_CreateDxgiSurfaceRenderTarget(this,A,B,C) (this)->lpVtbl->CreateDxgiSurfaceRenderTarget(this,A,B,C)
#define ID2D1Factory_CreateEllipseGeometry(this,A,B) (this)->lpVtbl->CreateEllipseGeometry(this,A,B)
#define ID2D1Factory_CreateGeometryGroup(this,A,B,C,D) (this)->lpVtbl->CreateGeometryGroup(this,A,B,C,D)
#define ID2D1Factory_CreateHwndRenderTarget(this,A,B,C) (this)->lpVtbl->CreateHwndRenderTarget(this,A,B,C)
#define ID2D1Factory_CreatePathGeometry(this,A) (this)->lpVtbl->CreatePathGeometry(this,A)
#define ID2D1Factory_CreateRectangleGeometry(this,A,B) (this)->lpVtbl->CreateRectangleGeometry(this,A,B)
#define ID2D1Factory_CreateRoundedRectangleGeometry(this,A,B) (this)->lpVtbl->CreateRoundedRectangleGeometry(this,A,B)
#define ID2D1Factory_CreateStrokeStyle(this,A,B,C,D) (this)->lpVtbl->CreateStrokeStyle(this,A,B,C,D)
#define ID2D1Factory_CreateTransformedGeometry(this,A,B,C) (this)->lpVtbl->CreateTransformedGeometry(this,A,B,C)
#define ID2D1Factory_CreateWicBitmapRenderTarget(this,A,B,C) (this)->lpVtbl->CreateWicBitmapRenderTarget(this,A,B,C)
#define ID2D1Factory_GetDesktopDpi(this,A,B) (this)->lpVtbl->GetDesktopDpi(this,A,B)
#define ID2D1Factory_ReloadSystemMetrics(this) (this)->lpVtbl->ReloadSystemMetrics(this)
You look at the "STDMETHOD" section of the definitions not the "#define" section.
Related
I have a specific question,
I have a binary that launch a shell with execv but the shell change the user and with gdb i can't seem to find where the user change is happening.
level0#RainFall:~$ whoami
level0
level0#RainFall:~$ ls -la
-rwsr-x---+ 1 level1 users 747441 Mar 6 2016 level0
level0#RainFall:~$ gdb
(gdb) file level0
Reading symbols from /home/user/level0/level0...(no debugging symbols found)...done.
(gdb) run 423
Starting program: /home/user/level0/level0 423
process 3718 is executing new program: /bin/dash
$ whoami
level0
But when I don't use gdb:
level0#RainFall:~$ ./level0 423
$ whoami
level1
$
Here is the disas of main
0x08048ec0 <+0>: push ebp
0x08048ec1 <+1>: mov ebp,esp
0x08048ec3 <+3>: and esp,0xfffffff0
0x08048ec6 <+6>: sub esp,0x20
0x08048ec9 <+9>: mov eax,DWORD PTR [ebp+0xc]
0x08048ecc <+12>: add eax,0x4
0x08048ecf <+15>: mov eax,DWORD PTR [eax]
0x08048ed1 <+17>: mov DWORD PTR [esp],eax
0x08048ed4 <+20>: call 0x8049710 <atoi>
0x08048ed9 <+25>: cmp eax,0x1a7
// it compare argv[1] with 423 if it is unequal it print No!
0x08048ede <+30>: jne 0x8048f58 <main+152>
0x08048ee0 <+32>: mov DWORD PTR [esp],0x80c5348
0x08048ee7 <+39>: call 0x8050bf0 <strdup>
0x08048eec <+44>: mov DWORD PTR [esp+0x10],eax
0x08048ef0 <+48>: mov DWORD PTR [esp+0x14],0x0
0x08048ef8 <+56>: call 0x8054680 <getegid>
0x08048efd <+61>: mov DWORD PTR [esp+0x1c],eax
0x08048f01 <+65>: call 0x8054670 <geteuid>
0x08048f06 <+70>: mov DWORD PTR [esp+0x18],eax
0x08048f0a <+74>: mov eax,DWORD PTR [esp+0x1c]
0x08048f0e <+78>: mov DWORD PTR [esp+0x8],eax
0x08048f12 <+82>: mov eax,DWORD PTR [esp+0x1c]
0x08048f16 <+86>: mov DWORD PTR [esp+0x4],eax
0x08048f1a <+90>: mov eax,DWORD PTR [esp+0x1c]
0x08048f1e <+94>: mov DWORD PTR [esp],eax
0x08048f21 <+97>: call 0x8054700 <setresgid>
0x08048f26 <+102>: mov eax,DWORD PTR [esp+0x18]
0x08048f2a <+106>: mov DWORD PTR [esp+0x8],eax
0x08048f2e <+110>: mov eax,DWORD PTR [esp+0x18]
0x08048f32 <+114>: mov DWORD PTR [esp+0x4],eax
0x08048f36 <+118>: mov eax,DWORD PTR [esp+0x18]
0x08048f3a <+122>: mov DWORD PTR [esp],eax
0x08048f3d <+125>: call 0x8054690 <setresuid>
0x08048f42 <+130>: lea eax,[esp+0x10]
0x08048f46 <+134>: mov DWORD PTR [esp+0x4],eax
0x08048f4a <+138>: mov DWORD PTR [esp],0x80c5348
//at this point euid and egid are the one of the user that launched gdb`
0x08048f51 <+145>: call 0x8054640 <execv>
// we never go there since execv opens a shell
0x08048f56 <+150>: jmp 0x8048f80 <main+192>
0x08048f58 <+152>: mov eax,ds:0x80ee170
0x08048f5d <+157>: mov edx,eax
0x08048f5f <+159>: mov eax,0x80c5350
0x08048f64 <+164>: mov DWORD PTR [esp+0xc],edx
0x08048f68 <+168>: mov DWORD PTR [esp+0x8],0x5
0x08048f70 <+176>: mov DWORD PTR [esp+0x4],0x1
0x08048f78 <+184>: mov DWORD PTR [esp],eax
0x08048f7b <+187>: call 0x804a230 <fwrite>
0x08048f80 <+192>: mov eax,0x0
0x08048f85 <+197>: leave
0x08048f86 <+198>: ret
End of assembler dump.
I don't understand how the binary changes behaviour if I execute it by gdb or in the shell, maybe its because the binary's proprietary is level1?
If someone has the time to explain to me how it works I'll be really greatful
Thanks a lot
I don't understand how the binary changes behaviour
The binary doesn't -- the kernel creates a new process with different UID when presented a set-uid binary (that's what s in -rwsr-x---+ means).
For obvious security reasons the kernel doesn't do that when the binary is being debugged.
I used this import definition in OSX32 successfully:
uses
MacApi.ObjectiveC,
MacApi.Foundation,
Macapi.CoreFoundation,
Macapi.Mach,
Macapi.IOKit;
type
io_iterator_t = io_object_t;
io_name_t = array[0..127] of AnsiChar;
function IORegistryEntrySearchCFProperty(entry: io_registry_entry_t;
plane: io_name_t; key: CFStringRef; allocator: CFAllocatorRef;
options: IOOptionBits): CFTypeRef; cdecl;
external libIOKit name _PU + 'IORegistryEntrySearchCFProperty';
function IOServiceGetMatchingServices(masterPort: mach_port_t;
matching: CFDictionaryRef; var existing: io_iterator_t): kern_return_t; cdecl;
external libIOKit name _PU + 'IOServiceGetMatchingServices';
function IOIteratorNext(name: io_iterator_t): io_object_t; cdecl;
external libIOKit name _PU + 'IOIteratorNext';
const
kIOSerialBSDServiceValue = 'IOSerialBSDClient';
kIOSerialBSDTypeKey = 'IOSerialBSDClientType';
kIOSerialBSDModemType = 'IOModemSerialStream';
kIOUSBDeviceClassName = 'IOUSBDevice';
kIOCalloutDeviceKey = 'IOCalloutDevice';
kIOTTYDeviceKey = 'IOTTYDevice';
kIOServicePlane = 'IOService';
kUSBInterfaceNumber = 'bInterfaceNumber';
kUSBVendorID = 'idVendor';
kUSBProductID = 'idProduct';
kIORegistryIterateRecursively = $00000001;
kIORegistryIterateParents = $00000002;
Since the migration to OSX64 I get a read access violation within the function IORegistryEntrySearchCFProperty.
From my point of view, there is no change in the parameters of IORegistryEntrySearchCFProperty from 32bit to 64bit.
The API function is used to read out vendor ID and the product ID of a USB device:
function TSerialInterface.SearchUSBSerialDevice(const Service: string; VendorID, ProductID: cardinal): integer;
var
MatchingDictionary: CFMutableDictionaryRef;
Iter: io_iterator_t;
USBRef: io_service_t;
ret: kern_return_t;
ResAsCFString: CFTypeRef;
aBsdPath: PAnsiChar;
Bsd: array[0..1024] of AnsiChar;
sBsd: string;
VID, PID: Int32;
begin
result := 0;
MatchingDictionary := IOServiceMatching(kIOSerialBSDServiceValue);
ret := IOServiceGetMatchingServices(kIOMasterPortDefault,
CFDictionaryRef(MatchingDictionary), Iter);
if (ret = KERN_SUCCESS) and (Iter <> 0) then
begin
try
repeat
USBRef := IOIteratorNext(Iter);
if USBRef <> 0 then
begin
// USB device found
Bsd[0] := #0;
VID := 0;
PID := 0;
ResAsCFString := IORegistryEntryCreateCFProperty(USBRef,
CFSTR(kIOCalloutDeviceKey), kCFAllocatorDefault, 0);
if assigned(ResAsCFString) then
begin
aBsdPath := CFStringGetCStringPtr(ResAsCFString,
kCFStringEncodingASCII);
if assigned(aBsdPath) then
sBsd := string(aBsdPath)
else if CFStringGetCString(ResAsCFString, #Bsd[0], sizeof(Bsd),
kCFStringEncodingASCII) then
sBsd := string(Bsd)
else
sBsd := ''; // Invalid device path
end;
ResAsCFString := IORegistryEntrySearchCFProperty(USBRef,
kIOServicePlane, CFSTR(kUSBVendorID), kCFAllocatorDefault,
kIORegistryIterateRecursively + kIORegistryIterateParents);
if assigned(ResAsCFString) then
if not CFNumberGetValue(ResAsCFString, kCFNumberIntType, #VID) then
VID := 0;
ResAsCFString := IORegistryEntrySearchCFProperty(USBRef,
kIOServicePlane, CFSTR(kUSBProductID), kCFAllocatorDefault,
kIORegistryIterateRecursively + kIORegistryIterateParents);
if assigned(ResAsCFString) then
if not CFNumberGetValue(ResAsCFString, kCFNumberIntType, #PID) then
PID := 0;
Log.d(name + ': USBDevice "' + sBsd + '" VID/PID: ' + IntToHex(VID) + '/' + IntToHex(PID));
end;
until USBRef = 0;
finally
IOObjectRelease(Iter);
end;
end;
I have implemented the above function also with C in XCode and can run this code without any troubles.
At exception (EAccessViolation: Access violation at address 00007FFF3A929716, accessing adress 000000000000000000) I see the following call stack in the Delphi IDE:
*System._DbgExcNotify(int, void*, System.SmallString<(unsigned char)255>*, void*, void*)(0,0x00000001039035e0,0x00000001012fa22e,0x00007fff3a929716,0x0000000000000000)
System.NotifyReRaise(System.TObject*, void*)(0x00000001039035e0,0x00007fff3a929716)
System._RaiseAtExcept(System.TObject*, void*)(0x00000001039035e0,0x00007fff3a929716)
System.Internal.Excutils.SignalConverter(NativeUInt, NativeUInt, NativeUInt)(140734176073494,0,11)
:000000010003CDE0 System::Internal::Excutils::GetExceptionObject(NativeUInt, NativeUInt, unsigned long)
:00007FFF3D27B2A0 IORegistryEntrySearchCFProperty
Serialinterface.TSerialInterface.SearchComPortForUSB(System.UnicodeString, unsigned int, unsigned int)(0x000000020978e5e0,'USBser',2283,65287)*
For deeper analyze, I have added here the generated assembler code of a small test procedure that calls IORegistryEntrySearchCFProperty.
Object Pascal in Unit3.pas:
procedure Test
var
USBRef: io_service_t;
key: CFStringRef;
allocator: CFAllocatorRef;
ResAsCFString: CFTypeRef;
begin
USBRef := 0;
key := CFSTR(kUSBVendorID);
allocator := kCFAllocatorDefault;
ResAsCFString := IORegistryEntrySearchCFProperty(USBRef,
kIOServicePlane, key, allocator, 0);
end;
The Delphi debugger CPU view shows the disassembled x64 code:
Unit3.pas.38: USBRef := 0;
000000010079CC43 C745FC00000000 mov dword ptr [rbp - 0x4], 0x0
Unit3.pas.39: key := CFSTR(kUSBVendorID);
000000010079CC4A 488D355B881000 lea rsi, [rip + 0x10885b]; __unnamed_1 + 12
000000010079CC51 488D7DD8 lea rdi, [rbp - 0x28]
000000010079CC55 E8E69987FF call 0x100016640; System.UTF8Encode(System.UnicodeString) at System.pas:39603
000000010079CC5A EB00 jmp 0x10079cc5c; <+44> at Unit3.pas:39
000000010079CC5C 488B7DD8 mov rdi, qword ptr [rbp - 0x28]
000000010079CC60 E85B9B87FF call 0x1000167c0; System._LStrToPChar(System.AnsiStringT<(unsigned short)0>) at System.pas:28783
000000010079CC65 48898538FFFFFF mov qword ptr [rbp - 0xc8], rax
000000010079CC6C EB00 jmp 0x10079cc6e; <+62> at Unit3.pas:39
000000010079CC6E 488BBD38FFFFFF mov rdi, qword ptr [rbp - 0xc8]
000000010079CC75 E8767789FF call 0x1000343f0; Macapi::Corefoundation::__CFStringMakeConstantString(char*)
000000010079CC7A 48898530FFFFFF mov qword ptr [rbp - 0xd0], rax
000000010079CC81 EB00 jmp 0x10079cc83; <+83> at Unit3.pas:39
000000010079CC83 488B8530FFFFFF mov rax, qword ptr [rbp - 0xd0]
000000010079CC8A 488945F0 mov qword ptr [rbp - 0x10], rax
Unit3.pas.40: allocator := kCFAllocatorDefault;
000000010079CC8E E8AD7A89FF call 0x100034740; Macapi.Corefoundation.kCFAllocatorDefault() at CFBaseImpl.inc:65
000000010079CC93 48898528FFFFFF mov qword ptr [rbp - 0xd8], rax
000000010079CC9A EB00 jmp 0x10079cc9c; <+108> at Unit3.pas:40
000000010079CC9C 488B8528FFFFFF mov rax, qword ptr [rbp - 0xd8]
000000010079CCA3 488945E8 mov qword ptr [rbp - 0x18], rax
Unit3.pas.41: ResAsCFString := IORegistryEntrySearchCFProperty(USBRef,
000000010079CCA7 8B7DFC mov edi, dword ptr [rbp - 0x4]
000000010079CCAA 0F28057F881000 movaps xmm0, xmmword ptr [rip + 0x10887f]; __unnamed_2 + 112
000000010079CCB1 0F2945C0 movaps xmmword ptr [rbp - 0x40], xmm0
000000010079CCB5 0F280564881000 movaps xmm0, xmmword ptr [rip + 0x108864]; __unnamed_2 + 96
000000010079CCBC 0F2945B0 movaps xmmword ptr [rbp - 0x50], xmm0
000000010079CCC0 0F280549881000 movaps xmm0, xmmword ptr [rip + 0x108849]; __unnamed_2 + 80
000000010079CCC7 0F2945A0 movaps xmmword ptr [rbp - 0x60], xmm0
000000010079CCCB 0F28052E881000 movaps xmm0, xmmword ptr [rip + 0x10882e]; __unnamed_2 + 64
000000010079CCD2 0F294590 movaps xmmword ptr [rbp - 0x70], xmm0
000000010079CCD6 0F280513881000 movaps xmm0, xmmword ptr [rip + 0x108813]; __unnamed_2 + 48
000000010079CCDD 0F294580 movaps xmmword ptr [rbp - 0x80], xmm0
000000010079CCE1 0F2805F8871000 movaps xmm0, xmmword ptr [rip + 0x1087f8]; __unnamed_2 + 32
000000010079CCE8 0F298570FFFFFF movaps xmmword ptr [rbp - 0x90], xmm0
000000010079CCEF 0F2805DA871000 movaps xmm0, xmmword ptr [rip + 0x1087da]; __unnamed_2 + 16
000000010079CCF6 0F298560FFFFFF movaps xmmword ptr [rbp - 0xa0], xmm0
000000010079CCFD 0F2805BC871000 movaps xmm0, xmmword ptr [rip + 0x1087bc]; __unnamed_2
000000010079CD04 0F298550FFFFFF movaps xmmword ptr [rbp - 0xb0], xmm0
000000010079CD0B 488B75F0 mov rsi, qword ptr [rbp - 0x10]
000000010079CD0F 488B55E8 mov rdx, qword ptr [rbp - 0x18]
000000010079CD13 4889E1 mov rcx, rsp
000000010079CD16 0F2845C0 movaps xmm0, xmmword ptr [rbp - 0x40]
000000010079CD1A 0F114170 movups xmmword ptr [rcx + 0x70], xmm0
000000010079CD1E 0F2845B0 movaps xmm0, xmmword ptr [rbp - 0x50]
000000010079CD22 0F114160 movups xmmword ptr [rcx + 0x60], xmm0
000000010079CD26 0F2845A0 movaps xmm0, xmmword ptr [rbp - 0x60]
000000010079CD2A 0F114150 movups xmmword ptr [rcx + 0x50], xmm0
000000010079CD2E 0F284590 movaps xmm0, xmmword ptr [rbp - 0x70]
000000010079CD32 0F114140 movups xmmword ptr [rcx + 0x40], xmm0
000000010079CD36 0F288550FFFFFF movaps xmm0, xmmword ptr [rbp - 0xb0]
000000010079CD3D 0F288D60FFFFFF movaps xmm1, xmmword ptr [rbp - 0xa0]
000000010079CD44 0F289570FFFFFF movaps xmm2, xmmword ptr [rbp - 0x90]
000000010079CD4B 0F285D80 movaps xmm3, xmmword ptr [rbp - 0x80]
000000010079CD4F 0F115930 movups xmmword ptr [rcx + 0x30], xmm3
000000010079CD53 0F115120 movups xmmword ptr [rcx + 0x20], xmm2
000000010079CD57 0F114910 movups xmmword ptr [rcx + 0x10], xmm1
000000010079CD5B 0F1101 movups xmmword ptr [rcx], xmm0
000000010079CD5E 31C9 xor ecx, ecx
> Register content here
> RBP: 00007FFEEFBFEA80
> RSP: 00007FFEEFBFEA00
> Memory content here
> 00007FFEEFBFEA00 49 4F 53 65 72 76 69 63 IOServic
> 00007FFEEFBFEA08 65 00 00 00 00 00 00 00 e.......
000000010079CD60 E82BFEFFFF call 0x10079cb90; Macapi::Iokit2::IORegistryEntrySearchCFProperty(unsigned int, System::StaticArray<char, 128>, __CFString*, __CFAllocator*, unsigned int)
> Access violation at address 00007FFF2ADD716, accessing address 0
000000010079CD65 48898520FFFFFF mov qword ptr [rbp - 0xe0], rax
000000010079CD6C EB00 jmp 0x10079cd6e; <+318> at Unit3.pas:41
000000010079CD6E 488B8520FFFFFF mov rax, qword ptr [rbp - 0xe0]
000000010079CD75 488945E0 mov qword ptr [rbp - 0x20], rax
000000010079CD79 EB37 jmp 0x10079cdb2; <+386> at Unit3.pas:41
000000010079CD7B 89D1 mov ecx, edx
000000010079CD7D 48898540FFFFFF mov qword ptr [rbp - 0xc0], rax
000000010079CD84 898D48FFFFFF mov dword ptr [rbp - 0xb8], ecx
000000010079CD8A 488D7DD8 lea rdi, [rbp - 0x28]
000000010079CD8E E81D9F87FF call 0x100016cb0; System._LStrClr(void*) at System.pas:25402
000000010079CD93 8B8D48FFFFFF mov ecx, dword ptr [rbp - 0xb8]
000000010079CD99 488BBD40FFFFFF mov rdi, qword ptr [rbp - 0xc0]
000000010079CDA0 48898518FFFFFF mov qword ptr [rbp - 0xe8], rax
000000010079CDA7 898D14FFFFFF mov dword ptr [rbp - 0xec], ecx
000000010079CDAD E8863B0100 call 0x1007b0938; symbol stub for: _Unwind_Resume
000000010079CDB2 488D45D8 lea rax, [rbp - 0x28]
Unit3.pas.47: end;
000000010079CDB6 4889C7 mov rdi, rax
000000010079CDB9 E8F29E87FF call 0x100016cb0; System._LStrClr(void*) at System.pas:25402
000000010079CDBE 48898508FFFFFF mov qword ptr [rbp - 0xf8], rax
000000010079CDC5 4881C480010000 add rsp, 0x180
000000010079CDCC 5D pop rbp
000000010079CDCD C3 ret
Do I have shown all concerned registers? (Unfortunately, I'm too far away from understanding the details of this x64 code).
Compared to the following C code written in XCode:
void Test(void)
{
io_service_t usbRef = 0;
CFStringRef key = CFSTR("idVendor");
CFAllocatorRef allocator = kCFAllocatorDefault;
CFTypeRef cf_vendor;
cf_vendor = IORegistryEntrySearchCFProperty(usbRef, kIOServicePlane, key, allocator, 0);
}
Generates this x64 assembly code:
0x100001c40 <+0>: pushq %rbp
0x100001c41 <+1>: movq %rsp, %rbp
0x100001c44 <+4>: subq $0x20, %rsp
0x100001c48 <+8>: xorl %r8d, %r8d
0x100001c4b <+11>: movq 0x3c6(%rip), %rax ; (void *)0x00007fff2fc755f0: kCFAllocatorDefault
0x100001c52 <+18>: leaq 0x4f7(%rip), %rcx ; #"idVendor"
0x100001c59 <+25>: movl $0x0, -0x4(%rbp)
0x100001c60 <+32>: movq %rcx, -0x10(%rbp)
0x100001c64 <+36>: movq (%rax), %rax
0x100001c67 <+39>: movq %rax, -0x18(%rbp)
-> 0x100001c6b <+43>: movl -0x4(%rbp), %edi
0x100001c6e <+46>: movq -0x10(%rbp), %rdx
0x100001c72 <+50>: movq -0x18(%rbp), %rcx
0x100001c76 <+54>: leaq 0x263(%rip), %rsi ; "IOService"
0x100001c7d <+61>: callq 0x100001d12 ; symbol stub for: IORegistryEntrySearchCFProperty
0x100001c82 <+66>: movq %rax, -0x20(%rbp)
0x100001c86 <+70>: addq $0x20, %rsp
0x100001c8a <+74>: popq %rbp
0x100001c8b <+75>: retq
Compared to the x86 code generated by Delphi 32bit compiler of the pascal test procedure which works as expected:
Unit3.pas.38: USBRef := 0;
004BB6E1 33C0 xor eax,eax
004BB6E3 8945FC mov [ebp-$04],eax
Unit3.pas.39: key := CFSTR(kUSBVendorID);
004BB6E6 6810000000 push $00000010
004BB6EB 55 push ebp
004BB6EC 68EDFEEFBE push $beeffeed
004BB6F1 83C4F4 add esp,-$0c
004BB6F4 83C4FC add esp,-$04
004BB6F7 8D55E8 lea edx,[ebp-$18]
004BB6FA 8D83A0B74B00 lea eax,[ebx+Test + $DC]
004BB700 E8276EB6FF call UTF8Encode
004BB705 83C404 add esp,$04
004BB708 8B45E8 mov eax,[ebp-$18]
004BB70B 83C4FC add esp,-$04
004BB70E E85904B6FF call #LStrToPChar
004BB713 83C404 add esp,$04
004BB716 50 push eax
004BB717 E8A0AD4400 call $009064bc
004BB71C 83C41C add esp,$1c
004BB71F FE4424F4 inc byte ptr [esp-$0c]
004BB723 8945EC mov [ebp-$14],eax
004BB726 8B45EC mov eax,[ebp-$14]
004BB729 8945F8 mov [ebp-$08],eax
Unit3.pas.40: allocator := kCFAllocatorDefault;
004BB72C 83C4F4 add esp,-$0c
004BB72F E8602EB7FF call kCFAllocatorDefault
004BB734 83C40C add esp,$0c
004BB737 8945F4 mov [ebp-$0c],eax
Unit3.pas.41: ResAsCFString := IORegistryEntrySearchCFProperty(USBRef,
004BB73A 6820000000 push $00000020
004BB73F 55 push ebp
004BB740 68EDFEEFBE push $beeffeed
004BB745 83C4F4 add esp,-$0c
004BB748 6A00 push $00
004BB74A 8B45F4 mov eax,[ebp-$0c]
004BB74D 50 push eax
004BB74E 8B45F8 mov eax,[ebp-$08]
004BB751 50 push eax
004BB752 8D83B4B74B00 lea eax,[ebx+Test + $F0]
> Register content here
> EAX: 004BB7B4
>Memory content here:
> 004BB7B4 49 4F 53 65 72 76 69 63 IOServic
> 004BB7BC 65 00 00 00 00 00 00 00 e.......
004BB758 50 push eax
004BB759 8B45FC mov eax,[ebp-$04]
004BB75C 50 push eax
004BB75D E8BEA84400 call $00906020
004BB762 83C42C add esp,$2c
004BB765 FE4424F4 inc byte ptr [esp-$0c]
004BB769 8945F0 mov [ebp-$10],eax
Unit3.pas.47: end;
004BB76C 688FB74B00 push $004bb78f
004BB771 011C24 add [esp],ebx
004BB774 8D45E8 lea eax,[ebp-$18]
004BB777 83C4F8 add esp,-$08
004BB77A E86DF7B5FF call #LStrClr
004BB77F 83C408 add esp,$08
004BB782 C3 ret
Maybe someone can give me a tip, what I have to pay attention to here.
The issue was in the declaration of the type io_name_t. For the Delphi MacOS64 in the procedure declaration, an array of AnsiChar is no longer identical to a PAnsiChar. The following solution works now:
type
io_name_t = PAnsiChar;
function IORegistryEntrySearchCFProperty(entry: io_registry_entry_t;
plane: io_name_t; key: CFStringRef; allocator: CFAllocatorRef;
options: IOOptionBits): CFTypeRef; cdecl;
external libIOKit name _PU + 'IORegistryEntrySearchCFProperty';
function for initiliase Schannel
SecureConnect proc uses ebx edi esi, _host: dword, _port: dword, phContext: dword, pCredHandle: dword, cSocket: dword
SECPKG_CRED_OUTBOUND equ 2
SCHANNEL_CRED_VERSION equ 4
SCH_CRED_NO_DEFAULT_CREDS equ 10h
SCH_CRED_MANUAL_CRED_VALIDATION equ 8
ISC_REQ_SEQUENCE_DETECT equ 8
ISC_REQ_REPLAY_DETECT equ 4
ISC_REQ_CONFIDENTIALITY equ 10h
ISC_RET_EXTENDED_ERROR equ 4000h
ISC_REQ_ALLOCATE_MEMORY equ 100h
ISC_REQ_STREAM equ 8000h
ISC_RET_EXTENDED_ERROR equ 4000h
SECURITY_NATIVE_DREP equ 10h
IO_BUFFER_SIZE equ 8000h
SEC_I_INCOMPLETE_CREDENTIALS equ 90320h
SEC_I_CONTINUE_NEEDED equ 90312h
SEC_E_INCOMPLETE_MESSAGE equ 80090318h
SCHANNEL_CRED STRUCT
dwVersion dd ?
cCreds dd ?
paCred dd ?
hRootStore dd ?
cMappers dd ?
aphMappers dd ?
cSupportedAlgs dd ?
palgSupportedAlgs dd ?
grbitEnabledProtocols dd ?
dwMinimumCipherStrength dd ?
dwMaximumCipherStrength dd ?
dwSessionLifespan dd ?
dwFlags dd ?
dwCredFormat dd ?
SCHANNEL_CRED ENDS
SecBufferDesc STRUCT
ulVersion dd ?
cBuffers dd ?
pBuffers dd ?
SecBufferDesc ENDS
SecBuffer STRUCT
cbBuffer dd ?
BufferType dd ?
pvBuffer dd ?
SecBuffer ENDS
CERT_CONTEXT STRUCT
dwCertEncodingType dd ?
pbCertEncoded dd ?
cbCertEncoded dd ?
pCertInfo dd ?
hCertStore dd ?
CERT_CONTEXT ENDS
local credentials : SCHANNEL_CRED
local sSocket : dword
local sin : sockaddr_in
local iMode : dword
local fd : fds_set
local dwSSPIFlags : dword
local out_buffer_desc : SecBufferDesc
local _out_buffer : SecBuffer
local in_buffer_desc : SecBufferDesc
local _in_buffer[2] : SecBuffer
local dwSSPIOutFlags : dword
local IoBuffer : dword
local cbIoBuffer : dword
local fDoRead : dword
local scRet : dword
local ExtraData : SecBuffer
lea ecx, [ebp - 3 * 4]
sub ecx, esp
invoke ZeroMemory, addr [esp + 3 * 4 + 4], ecx
mov credentials.dwVersion, SCHANNEL_CRED_VERSION
mov credentials.dwFlags, SCH_CRED_NO_DEFAULT_CREDS or SCH_CRED_MANUAL_CRED_VALIDATION
invoke AcquireCredentialsHandleA, NULL, _T("Microsoft Unified Security Protocol Provider"), SECPKG_CRED_OUTBOUND, NULL, addr credentials, NULL, NULL, dword ptr [pCredHandle], NULL
.if eax == 0
invoke socket, AF_INET, SOCK_STREAM, IPPROTO_TCP
mov dword ptr [sSocket], eax
invoke copydata, addr sSocket, dword ptr [cSocket], sizeof dword
invoke isip, dword ptr [_host]
.if eax != 0
mov eax, dword ptr [_host]
jmp #f
.endif
invoke xgethostbyname, dword ptr [_host], AF_INET
invoke inet_ntoa, eax
##:
invoke inet_addr, eax
mov sin.sin_addr, eax
mov eax, dword ptr [_port]
cmp eax, 65536
jna #f
invoke atoi, eax
##:
invoke htons, eax
mov sin.sin_port, ax
mov sin.sin_family, AF_INET ;???????? ???? ? ??? "AF_INET"
mov iMode, 1
invoke setsockopt, dword ptr [sSocket], IPPROTO_TCP, TCP_NODELAY, addr iMode, 4
mov iMode, 1
invoke ioctlsocket, dword ptr [sSocket], FIONBIO, addr iMode
invoke connect, dword ptr [sSocket], addr sin, sizeof sin ;??????????? ?????? ????????
invoke fd_set_, dword ptr [sSocket], 0, addr fd, 10, 0
invoke select, 0, 0, addr fd, 0, addr [fd + 4 * 3]
cmp eax, 1
jnz close
mov iMode, 0
invoke ioctlsocket, dword ptr [sSocket], FIONBIO, addr iMode
mov dword ptr [dwSSPIFlags], ISC_REQ_SEQUENCE_DETECT or ISC_REQ_REPLAY_DETECT or ISC_REQ_CONFIDENTIALITY or ISC_RET_EXTENDED_ERROR or ISC_REQ_ALLOCATE_MEMORY or ISC_REQ_STREAM
mov _out_buffer.cbBuffer, 0
mov _out_buffer.BufferType, SECBUFFER_TOKEN
mov _out_buffer.pvBuffer, NULL
mov out_buffer_desc.ulVersion, SECBUFFER_VERSION
mov out_buffer_desc.cBuffers, 1
lea eax, _out_buffer
mov out_buffer_desc.pBuffers, eax
invoke InitializeSecurityContextA, dword ptr [pCredHandle], NULL, dword ptr [_host], dword ptr [dwSSPIFlags], 0, SECURITY_NATIVE_DREP, NULL, 0, dword ptr [phContext], addr out_buffer_desc, addr dwSSPIOutFlags, NULL
.if _out_buffer.cbBuffer != 0 && _out_buffer.pvBuffer != NULL
invoke synsend, dword ptr [sSocket], _out_buffer.pvBuffer, _out_buffer.cbBuffer, NULL
invoke FreeContextBuffer, dword ptr [_out_buffer.pvBuffer]
invoke VirtualAlloc, 0, IO_BUFFER_SIZE, MEM_COMMIT or MEM_RESERVE, PAGE_READWRITE
test eax, eax
jz close
mov dword ptr [IoBuffer], eax
mov dword ptr [scRet], SEC_I_CONTINUE_NEEDED
mov dword ptr [cbIoBuffer], 0
mov dword ptr [fDoRead], TRUE
.while dword ptr [scRet] == SEC_I_CONTINUE_NEEDED || dword ptr [scRet] == SEC_E_INCOMPLETE_MESSAGE || dword ptr [scRet] == SEC_I_INCOMPLETE_CREDENTIALS
.if dword ptr [cbIoBuffer] == 0 || dword ptr [scRet] == SEC_E_INCOMPLETE_MESSAGE
.if dword ptr [fDoRead] == TRUE
mov eax, dword ptr [IoBuffer]
add eax, dword ptr [cbIoBuffer]
mov ecx, IO_BUFFER_SIZE
sub ecx, dword ptr [cbIoBuffer]
invoke recv_, dword ptr [sSocket], eax, ecx, 10
.break .if eax == 0 || sdword ptr eax < 0
add dword ptr [cbIoBuffer], eax
.else
mov dword ptr [fDoRead], TRUE
.endif
.endif
mov _out_buffer.cbBuffer, 0
mov _out_buffer.BufferType, SECBUFFER_TOKEN
mov _out_buffer.pvBuffer, NULL
mov out_buffer_desc.ulVersion, SECBUFFER_VERSION
mov out_buffer_desc.cBuffers, 1
lea eax, _out_buffer
mov out_buffer_desc.pBuffers, eax
mov eax, dword ptr [IoBuffer]
mov ecx, dword ptr [cbIoBuffer]
mov (0Ch * 0) + _in_buffer.cbBuffer, ecx
mov (0Ch * 0) + _in_buffer.BufferType, SECBUFFER_TOKEN
mov (0Ch * 0) + _in_buffer.pvBuffer, eax
mov (0Ch * 1) + _in_buffer.cbBuffer, 0
mov (0Ch * 1) + _in_buffer.BufferType, SECBUFFER_EMPTY
mov (0Ch * 1) + _in_buffer.pvBuffer, NULL
mov in_buffer_desc.ulVersion, SECBUFFER_VERSION
mov in_buffer_desc.cBuffers, 2
lea eax, _in_buffer
mov in_buffer_desc.pBuffers, eax
invoke InitializeSecurityContextA, dword ptr [pCredHandle], dword ptr [phContext], NULL, dword ptr [dwSSPIFlags], 0, SECURITY_NATIVE_DREP, addr in_buffer_desc, 0, NULL, addr out_buffer_desc, addr dwSSPIOutFlags, NULL
mov dword ptr [scRet], eax
.continue .if dword ptr [scRet] == SEC_E_INCOMPLETE_MESSAGE
.break .if sdword ptr [scRet] < 0
.if dword ptr [scRet] == SEC_E_OK || dword ptr [scRet] == SEC_I_CONTINUE_NEEDED && _out_buffer.cbBuffer != 0 && _out_buffer.pvBuffer != NULL
invoke synsend, dword ptr [sSocket], _out_buffer.pvBuffer, _out_buffer.cbBuffer, NULL
invoke FreeContextBuffer, dword ptr [_out_buffer.pvBuffer]
.endif
.if dword ptr [scRet] == SEC_I_INCOMPLETE_CREDENTIALS
invoke MessageBoxA, 0, _T("SEC_I_INCOMPLETE_CREDENTIALS"), 0, 0
;//GetNewClientCredentials(phCreds, dword ptr [phContext]);
;// Повторная попытка.
;fDoRead = FALSE;
;scRet = SEC_I_CONTINUE_NEEDED;
;// Исправляем ошибку Platform SDK!
;// Считаем, что за этим сообщением не может следовать другое
;cbIoBuffer = 0;
;.continue
.endif
.if dword ptr [(0Ch * 1) + _in_buffer.BufferType] == SECBUFFER_EXTRA
mov eax, dword ptr [IoBuffer]
add eax, dword ptr [cbIoBuffer]
mov ecx, (0Ch * 1) + _in_buffer.cbBuffer
mov dword ptr [cbIoBuffer], ecx
sub eax, ecx
invoke copydata, eax, dword ptr [IoBuffer], (0Ch * 1) + _in_buffer.cbBuffer
.else
mov dword ptr [cbIoBuffer], 0
.endif
.endw
invoke VirtualFree, dword ptr [IoBuffer], 0, MEM_RELEASE
cmp dword ptr [scRet], SEC_E_OK
jnz close
mov eax, dword ptr [sSocket]
jmp _ret
.endif
.endif
close:
xor eax, eax
_ret:
ret
SecureConnect endp
decryptmessage
cryptrecv proc uses ebx edi esi, _socket: dword, rbuffer: dword, phContext: dword
IO_BUFFER_SIZE equ 8000h
SecBufferDesc STRUCT
ulVersion dd ?
cBuffers dd ?
pBuffers dd ?
SecBufferDesc ENDS
SecBuffer STRUCT
cbBuffer dd ?
BufferType dd ?
pvBuffer dd ?
SecBuffer ENDS
local Cbuffer : dword
local cb : dword
local _edx : dword
local in_buffer_desc : SecBufferDesc
local _in_buffer[4] : SecBuffer
local scRet : dword
local _result : dword
lea ecx, [ebp - 3 * 4]
sub ecx, esp
invoke ZeroMemory, addr [esp + 3 * 4 + 4], ecx
invoke ZeroMemory, dword ptr [rbuffer], 4
mov edi, dword ptr [rbuffer]
mov dword ptr [_edx], IO_BUFFER_SIZE
invoke VirtualAlloc, 0, dword ptr [_edx], MEM_COMMIT or MEM_RESERVE, PAGE_READWRITE
test eax, eax
jz close
mov dword ptr [Cbuffer], eax
_recv:
.if dword ptr [cb] == 0 || dword ptr [scRet] == SEC_E_INCOMPLETE_MESSAGE
##:
mov eax, dword ptr [Cbuffer]
add eax, dword ptr [cb]
mov ecx, dword ptr [_edx]
sub ecx, dword ptr [cb]
test ecx, ecx
jnz #f
add dword ptr [_edx], IO_BUFFER_SIZE
invoke VirtualAlloc, 0, dword ptr [_edx], MEM_COMMIT or MEM_RESERVE, PAGE_READWRITE
test eax, eax
jz close
mov esi, eax
invoke copydata, dword ptr [Cbuffer], esi, dword ptr [cb]
invoke VirtualFree, dword ptr [Cbuffer], 0, MEM_RELEASE
mov dword ptr [Cbuffer], esi
jmp #b
##:
invoke recv, dword ptr [_socket], eax, ecx, 0
test eax, eax
jle close
add dword ptr [cb], eax
.endif
invoke copydata, addr cb, addr [(0Ch * 0) + _in_buffer.cbBuffer], 4
mov (0Ch * 0) + _in_buffer.BufferType, SECBUFFER_DATA
invoke copydata, addr Cbuffer, addr [(0Ch * 0) + _in_buffer.pvBuffer], 4
mov (0Ch * 1) + _in_buffer.cbBuffer, 0
mov (0Ch * 1) + _in_buffer.BufferType, SECBUFFER_EMPTY
mov (0Ch * 1) + _in_buffer.pvBuffer, NULL
mov (0Ch * 2) + _in_buffer.cbBuffer, 0
mov (0Ch * 2) + _in_buffer.BufferType, SECBUFFER_EMPTY
mov (0Ch * 2) + _in_buffer.pvBuffer, NULL
mov (0Ch * 3) + _in_buffer.cbBuffer, 0
mov (0Ch * 3) + _in_buffer.BufferType, SECBUFFER_EMPTY
mov (0Ch * 3) + _in_buffer.pvBuffer, NULL
lea eax, _in_buffer
mov in_buffer_desc.pBuffers, eax
mov in_buffer_desc.ulVersion, SECBUFFER_VERSION
mov in_buffer_desc.cBuffers, 4
invoke DecryptMessage, dword ptr [phContext], addr in_buffer_desc, 0, NULL
mov dword ptr [scRet], eax
cmp dword ptr [scRet], SEC_E_INCOMPLETE_MESSAGE
jz _recv
cmp dword ptr [scRet], SEC_I_CONTEXT_EXPIRED
jz close
.if dword ptr [scRet] == SEC_I_RENEGOTIATE
invoke MessageBoxA, 0, _T("SEC_I_RENEGOTIATE"), 0, 0
jmp close
.endif
cmp eax, SEC_E_OK
jnz close
mov dword ptr [cb], 0
mov ebx, 1
.while ebx <= 3
imul ecx, ebx, 0Ch
lea esi, [ecx + _in_buffer]
.if dword ptr [esi + SecBuffer.BufferType] == SECBUFFER_DATA && dword ptr [esi + SecBuffer.cbBuffer] != 0
.if dword ptr [edi] == NULL
invoke VirtualAlloc, 0, dword ptr [esi + SecBuffer.cbBuffer], MEM_COMMIT or MEM_RESERVE, PAGE_READWRITE
test eax, eax
jz close
mov dword ptr [edi], eax
invoke copydata, dword ptr [esi + SecBuffer.pvBuffer], dword ptr [edi], dword ptr [esi + SecBuffer.cbBuffer]
.else
mov ecx, dword ptr [_result]
add ecx, dword ptr [esi + SecBuffer.cbBuffer]
invoke VirtualAlloc, 0, ecx, MEM_COMMIT or MEM_RESERVE, PAGE_READWRITE
test eax, eax
jz close
mov edx, dword ptr [edi]
mov dword ptr [edi], eax
invoke copydata, edx, eax, dword ptr [_result]
invoke VirtualFree, edx, 0, MEM_RELEASE
mov eax, dword ptr [edi]
add eax, dword ptr [_result]
invoke copydata, dword ptr [esi + SecBuffer.pvBuffer], eax, dword ptr [esi + SecBuffer.cbBuffer]
.endif
mov eax, dword ptr [esi + SecBuffer.cbBuffer]
add dword ptr [_result], eax
.elseif dword ptr [esi + SecBuffer.BufferType] == SECBUFFER_EXTRA
mov edx, dword ptr [Cbuffer]
add edx, dword ptr [cb]
mov ecx, dword ptr [esi + SecBuffer.cbBuffer]
add dword ptr [cb], ecx
mov dword ptr [scRet], SEC_I_CONTINUE_NEEDED
invoke copydata, dword ptr [esi + SecBuffer.pvBuffer], edx, dword ptr [esi + SecBuffer.cbBuffer]
.endif
inc ebx
.endw
cmp dword ptr [scRet], SEC_I_CONTINUE_NEEDED
jz _recv
jmp _ret
close:
invoke VirtualFree, dword ptr [edi], 0, MEM_RELEASE
mov dword ptr [_result], NULL
_ret:
invoke VirtualFree, dword ptr [Cbuffer], 0, MEM_RELEASE
mov eax, dword ptr [_result]
ret
cryptrecv endp
this code work good. but sometime DecryptMessage fail with access violation. it cant read data from dword ptr [Cbuffer]
i am see it in debugger. and after error it say me that memory from dword ptr [Cbuffer] not allocated
access violation has occured inside DecryptMessage windows api function.
instruction that occure
movzx ecx, byte ptr [edi + 3]
in edi placed address that have dword ptr [Cbuffer]
Unfortunately, I had to re-image my laptop to install Visual Studio 2012. My project build but with above warning. Previously I had Visual Studio 2010 and I never got the above warning. The code is as follows:
__asm
{
//Initialize pointers on matrices
mov eax, dword ptr [this]
mov ebx, dword ptr [eax+UPkk]
mov dword ptr [UPkk_ptr],ebx
mov ebx, dword ptr [eax+UPk1k]
mov dword ptr [UPk1k_ptr],ebx
mov ebx, dword ptr [eax+DPk1k]
mov dword ptr [DPk1k_ptr],ebx
mov ebx, dword ptr [eax+DPkk]
mov dword ptr [DPkk_ptr],ebx
mov ebx, dword ptr [eax+mat_A]
mov dword ptr [mat_A_ptr],ebx
mov ebx, dword ptr [eax+vec_a]
mov dword ptr [vec_a_ptr],ebx
mov ebx, dword ptr [eax+vec_b]
mov dword ptr [vec_b_ptr],ebx
}
Do I need to change any settings in the project?
Best Regards
Chintan
Edit: In the above code when I replace ebx with ecx, the warnings go away and the code works fine. However, there is another piece of code where I have used ebx and ecx and in that case my program crashes. Here is the code:
__asm
{
//Initialize UPk1k[idx_4] pointer
mov eax, dword ptr [UPk1k_ptr]
mov ebx, dword ptr [idx_4]
imul ebx,8
add eax,ebx
mov dword ptr [UPk1k_id4_ptr],eax
//Initialize UPkk[idx_4] pointer
mov eax, dword ptr [UPkk_ptr]
mov ebx, dword ptr [idx_4]
imul ebx,8
add eax,ebx
mov dword ptr [UPkk_id4_ptr],eax
//Initialize UPk1k[idx_4] pointer
mov eax, dword ptr [vec_b_ptr]
mov ebx, dword ptr [idx_1]
imul ebx,8
add eax,ebx
mov dword ptr [vec_b_id1_ptr],eax
mov edi, dword ptr [idx_1] //Load idx_1 in edi
mov esi, 0 //initialize loop counter
jmp start_proc11
start_for11:inc esi //idx_2++
start_proc11:cmp esi, edi //idx_2<idx_1 ?
jge end_for11 //If yes so end of the loop
mov eax, UPk1k_id4_ptr //load UPk1k[idx_4] adress
mov ebx, vec_b_ptr //load vec_b adress
mov ecx, esi
imul ecx,8
add eax, ecx //UPk1k[idx_4+idx_2] in eax
add ebx, ecx //vec_b[idx_2] in eax
fld qword ptr [eax]//push UPk1k[idx_4+idx_2]
fld qword ptr [ebx] //push vec_b[idx_2]
mov edx,dword ptr [Sd_ptr]
fmul qword ptr [edx] //vec_b[idx_2]*Sd
fadd //pop UPk1k[idx_4+idx_2]+vec_b[idx_2]*Sd
mov edx,dword ptr [UPkk_id4_ptr]
fstp qword ptr [edx+esi*8] //pop UPkk[idx_4+idx_2]=UPk1k[idx_4+idx_2]+vec_b[idx_2]*Sd
fld qword ptr [ebx] //push vec_b[idx_2]
mov edx,dword ptr [vec_b_id1_ptr]
fld qword ptr [edx] //push vec_b[idx_2]
fmul qword ptr [eax]
fadd
fstp qword ptr [ebx]
jmp start_for11 //end of the loop
end_for11:
}
Many Thanks
Best Regards
CS
See MSDN about registers and that warning. They explain why the warning is produced: it forces the compiler to preserve value of EBX, which might be counter-productive to performance, the usual reason inline asm is used. Relevant quote:
In addition, by using EBX, ESI or EDI in inline assembly code, you
force the compiler to save and restore those registers in the function
prologue and epilogue.
To disable the warning, I think the syntax is
#pragma warning( disable : 4731 )
However, I'd try to use some other register instead, because the warning is there for a good reason, really, like most warnings.
In fact, Looking at your asm code, simply replace ebx With ecx, that should solve the problem.
This code is a C program (bubble sort) disassembled into assembly. How can I make the following code run if I put it in a .asm file and use nasm to assemble? If you know what needs changing, please say what to change it to. For instance I understand that nasm won't accept DWORD PTR, but I haven't found out what to do instead. Thanks
.file "sort.c" .intel_syntax noprefix .text .globl
sort .type sort, #function
sort: .LFB0:
.cfi_startproc
push rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
mov rbp, rsp
.cfi_def_cfa_register 6
mov QWORD PTR [rbp-24], rdi
mov DWORD PTR [rbp-28], esi
mov DWORD PTR [rbp-12], 0
jmp .L2
.L6:
mov DWORD PTR [rbp-8], 0
jmp .L3
.L5:
mov eax, DWORD PTR [rbp-8]
cdqe
sal rax, 2
add rax, QWORD PTR [rbp-24]
mov edx, DWORD PTR [rax]
mov eax, DWORD PTR [rbp-8]
cdqe
add rax, 1
sal rax, 2
add rax, QWORD PTR [rbp-24]
mov eax, DWORD PTR [rax]
cmp edx, eax
jle .L4
mov eax, DWORD PTR [rbp-8]
cdqe
sal rax, 2
add rax, QWORD PTR [rbp-24]
mov eax, DWORD PTR [rax]
mov DWORD PTR [rbp-4], eax
mov eax, DWORD PTR [rbp-8]
cdqe
sal rax, 2
add rax, QWORD PTR [rbp-24]
mov edx, DWORD PTR [rbp-8]
movsx rdx, edx
add rdx, 1
sal rdx, 2
add rdx, QWORD PTR [rbp-24]
mov edx, DWORD PTR [rdx]
mov DWORD PTR [rax], edx
mov eax, DWORD PTR [rbp-8]
cdqe
add rax, 1
sal rax, 2
add rax, QWORD PTR [rbp-24]
mov edx, DWORD PTR [rbp-4]
mov DWORD PTR [rax], edx
.L4:
add DWORD PTR [rbp-8], 1
.L3:
mov eax, DWORD PTR [rbp-28]
sub eax, 1
sub eax, DWORD PTR [rbp-12]
cmp eax, DWORD PTR [rbp-8]
jg .L5
add DWORD PTR [rbp-12], 1
.L2:
mov eax, DWORD PTR [rbp-28]
sub eax, 1
cmp eax, DWORD PTR [rbp-12]
jg .L6
pop rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size sort, .-sort
.ident "GCC: (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3"
.section .note.GNU-stack,"",#progbits
Just remove PTR and all nonsensical .somethings.
This assembles just fine:
; file: gas-nasm-sort.asm
bits 64
sort:
push rbp
mov rbp, rsp
mov QWORD [rbp-24], rdi
mov DWORD [rbp-28], esi
mov DWORD [rbp-12], 0
jmp .L2
.L6:
mov DWORD [rbp-8], 0
jmp .L3
.L5:
mov eax, DWORD [rbp-8]
cdqe
sal rax, 2
add rax, QWORD [rbp-24]
mov edx, DWORD [rax]
mov eax, DWORD [rbp-8]
cdqe
add rax, 1
sal rax, 2
add rax, QWORD [rbp-24]
mov eax, DWORD [rax]
cmp edx, eax
jle .L4
mov eax, DWORD [rbp-8]
cdqe
sal rax, 2
add rax, QWORD [rbp-24]
mov eax, DWORD [rax]
mov DWORD [rbp-4], eax
mov eax, DWORD [rbp-8]
cdqe
sal rax, 2
add rax, QWORD [rbp-24]
mov edx, DWORD [rbp-8]
movsx rdx, edx
add rdx, 1
sal rdx, 2
add rdx, QWORD [rbp-24]
mov edx, DWORD [rdx]
mov DWORD [rax], edx
mov eax, DWORD [rbp-8]
cdqe
add rax, 1
sal rax, 2
add rax, QWORD [rbp-24]
mov edx, DWORD [rbp-4]
mov DWORD [rax], edx
.L4:
add DWORD [rbp-8], 1
.L3:
mov eax, DWORD [rbp-28]
sub eax, 1
sub eax, DWORD [rbp-12]
cmp eax, DWORD [rbp-8]
jg .L5
add DWORD [rbp-12], 1
.L2:
mov eax, DWORD [rbp-28]
sub eax, 1
cmp eax, DWORD [rbp-12]
jg .L6
pop rbp
ret
Command:
nasm gas-nasm-sort.asm -f bin -o gas-nasm-sort.bin
But again, there's NASM documentation. Read it. In particular these sections:
2.2.2 NASM Requires Square Brackets For Memory References
2.2.3 NASM Doesn't Store Variable Types