Lost Page
novembre 12th, 2007 at 02:31 admin
Il y des jours comme ca, on croit avoir une bonne idée, on commence à coder un peu, sans trop réfléchir, pour se rendre compte qu’en fait, c’est super chaud ce qu’on veut faire … C’est marrant de voir comment on peut chier dans la colle parfois. J’étais en train de ranger ma collection de RSS (170 au total) quand je me suis dit qu’on devait pouvoir tricker avec la mémoire user-land non explorée.
Je me suis donc coder un petit prog qui alloue les dernières portions de mémoire avant l’adresse 0×80000000.
#include <windows.h> #include <stdio.h> #pragma comment (lib, "ntdll.lib") extern "C" ULONG __stdcall NtAllocateVirtualMemory( IN HANDLE ProcessHandle, IN OUT PVOID *BaseAddress, IN ULONG ZeroBits, IN OUT PULONG AllocationSize, IN ULONG AllocationType, IN ULONG Protect ); ULONG main(int argc, char * argv[]) { ULONG Status, Size=0x1000, A; PVOID Addr; for(A=0x70, Addr=0; A<0x80; A++, Addr=0) { Addr=(PVOID)((A<<24)+0xFF0000); printf("Addr: 0x%x\n", Addr); Status=NtAllocateVirtualMemory((HANDLE)-1, &Addr, 0, &Size, MEM_RESERVE|MEM_COMMIT|MEM_TOP_DOWN, PAGE_EXECUTE_READWRITE); if(Status) printf("Error with NtAllocateVirtualMemory : 0x%x\n", Status); else printf("RULZ\n"); VirtualFree(Addr, Size, MEM_RELEASE); } return 0; }
A l’exécution j’obtiens :
[...] Addr: 0x7dff0000 RULZ Addr: 0x7eff0000 RULZ Addr: 0x7fff0000 Error with NtAllocateVirtualMemory : 0xc00000f0
WTF avec l’addr 0x7fff00, la fonction NtAllocateVirtualMemory renvoie STATUS_INVALID_PARAMETER_2, qui veut dire que l’adresse d’allocation n’est pas bonne … Un petit doute s’empare de moi, ai-je mal retenu la limite entre le user-land et le kernel ? OK je sors le kd et je dump quelques constantes :
kd> ? poi(nt!MmSystemRangeStart) Evaluate expression: -2147483648 = 80000000
Cool, le kernel-land commence bien en 0×80000000. Je regarde l’adresse user-land la plus élevée possible qui normalement devrait être 0x7fffffff :
kd> ? poi(nt!MmHighestUserAddress) Evaluate expression: 2147418111 = 7ffeffff
Bim en plein dans mon cul, la fonction NtAllocateVirtualMemory vérifie que l’adresse d’allocation + la taille demandé ne dépasse pas MmHighestUserAddress et renvoie une erreur sinon. Un rapide calcul nous montre que MmSystemRangeStart-MmHighestUserAddress=0×1001, soit 4Ko (une page !) allant de 0x7fff000 à 0x7fffffff qui ne seront jamais utilisé par le process.
J’étais donc partit sur l’idée d’exploiter cette sorte de no man’s land pour y cacher des dates, du codes, voir même des chocapicz. Comme la seule fonction user-land capable d’allouer de la mémoire est NtAllocateVirtualMemory il me fallait concevoir à driver qui allait servir à ajouter cette zone mémoire dans le context de mon process.
Avec mon driver il est évident que je n’allais pas utiliser ZwAllocateMemory, j’ai donc décidé de jouer avec les MDL. Processus classique, j’alloue un buffer de la taille d’une page (PAGE_SIZE) dans la paged pool du kernel avec ExAllocatePoolWithTag puis je crée un MDL avec IoAllocateMdl qui représente la page de ce buffer. Ensuite MmProbeAndLockPages pour que ma page soit résidente en mémoire (jamais swappée) et enfin MmMapLockedPagesSpecifyCache pour mapper ma page à l’adresse 0x7fff0000 et là c’est le drame ! MmMapLockedPagesSpecifyCache contrôle aussi que l’allocation se fait bien à une adresse inférieure à 7ffeffff, ouinnz !
A partir de ce moment, je commence à désespérer, je sens que j’ai encore eu une idée en mousse. Arrive un moment ou je me dis que la solution la plus évidente serait d’ajouter moi même ma page dans l’espace mémoire du process. Mais pour cela, il faut s’attaquer à l’enfer qu’est la pagination … Pour ceux qui connaissent déjà, ils peuvent sauter ce post et m’aider un coder mon tool
Bion, un process dispose d’un espace user-land de 2Go virtuellement disponible. Cela signifie qu’il existe un mécanisme faisant croire au process qu’il dispose de 2Go de RAM alors qu’en réalité vous en avez juste assez pour faire tourner démineur sous Vista, c’est à dire 1 Go :p. Concrètement, le process manipule des addresse virtuelles qui peuvent aller de 0×0000000 à 0x7ffeffff, le système va effectuer une translation d’adresse pour retrouver l’adresse physique correspondante dans la RAM. Comme il ya au maximum 4GO de RAM allouable sur un système x86 32 bits il existe une extension kernel appelée PAE qui permet de profiter pleinement de toute votre mémoire, je ne m’attarderais pas dessus.
Chaque process va donc allouer son codes et ses datas dans les zones mémoire de son choix, seules les pages nécessaires seront utilisées physiquement. Cependant comme un programme à son propre espace mémoire de 2Go, il faut bien évidement que l’adresses 0×400000 ne renvoie pas sur la même adresse physique pour le processs A et pour le process B. C’est là qu’on rentre dans le principe de la pagination.
En gros chaque process possède une table qui lui est propre, servant à translater les adresses virtuelles en adresses physiques. Cette table se présente sous la forme d’un tableau de tableaux. Le premier tableau contient des Page Directorie Entries (PDE), le second des Page Table Entries (PTE). Chaque process possède 1024 (0×400) PDE et chaque PDE possède 1024 PTEs. Un PTE représente un page mémoire c’est à dire 4Ko. Si on calcul, 1024*1024*4096=2^32, on a bien toute notre mémoire de représentée. Les PDE et PTE on la forme suivante :
Pour plus d’infos je vous laisse lire les man intels. Ce qu’il faut retenir ce sont les champs « Page-Table Base Address » et « Page Base Address ». En fait, un PDE va référencer un PTE à travers son l’indice de sa page dans la RAM. Par exemple si j’ai un PDE avec un Page-Table Base Address de 0×879, alors ma table de PTEs commence à 0×879*PAGE_SIZE en RAM. Une adresse virtuelle sert à indiquer quels PDE et PTE sont utilisés pour retrouver son adresse physique. Celle-ci est découpée en 3 parties comme vous le voyez sur le schéma suivant :
Si je prends l’adresse virtuelle 0x7e390000 alors l’indice du PDE parmi les 1024 existant est 0x1f8 :
kd> ? 7e390000 >>0x16 Evaluate expression: 504 = 000001f8
L’indice de son PTE parmit les 1024 est 0×390 :
kd> ? (7e390000 & 3FF000)>>0xC Evaluate expression: 912 = 00000390
Les 12 derniers bytes servent à indiquer à quel offset nos données se trouvent dans la page. Au final on a donc :
J’ai aussi dit que chaque process avait sa propre table de PDEs. Cela est réalisé grâce au registre cr3 qui contient l’adresse physique du tableau de PDE, on retrouve cette valeur dans l’KPROCESS dans le champ DirectoryTableBase (offset 0×18) :
804e3592 cc int 3 kd> !process -1 PROCESS 84256da0 SessionId: 0 Cid: 02d4 Peb: 7ffd5000 ParentCid: 03ac DirBase: 01d62000 ObjectTable: e110bef8 HandleCount: 23. Image: instdrv.exe VadRoot ffa5c058 Vads 31 Clone 0 Private 48. Modified 1334. Locked 0. DeviceMap e1716068 Token e1110040 ElapsedTime 06:17:31.720 UserTime 00:00:00.040 KernelTime 00:00:00.440 QuotaPoolUsage[PagedPool] 15360 QuotaPoolUsage[NonPagedPool] 1240 Working Set Sizes (now,min,max) (322, 50, 345) (1288KB, 200KB, 1380KB) PeakWorkingSetSize 322 VirtualSize 12 Mb PeakVirtualSize 12 Mb PageFaultCount 319 MemoryPriority BACKGROUND BasePriority 8 CommitCharge 91 THREAD ffa07030 Cid 02d4.02bc Teb: 7ffdf000 Win32Thread: e1117d90 WAIT: (WrUserRequest) UserMode Non-Alertable 80dd8138 SynchronizationEvent kd> dt nt!_KPROCESS 84256da0 +0x000 Header : _DISPATCHER_HEADER +0x010 ProfileListHead : _LIST_ENTRY [ 0x84256db0 - 0x84256db0 ] +0x018 DirectoryTableBase : [2] 0x1d62000 [..]
A noter que le tableau des PDEs se retrouve toujours à l’adresse virtuelle 0xC0300000
Maintenant on va prendre un exemple concret ! Dans le cas suivant, j’ai fait en sorte que KD se retrouve dans le context d’un process nommé instdrv.exe.
kd> .process /i 84256da0 You need to continue execution (press 'g') for the context to be switched. When the debugger breaks in again, you will be in the new process context. kd> g Break instruction exception - code 80000003 (first chance) nt!RtlpBreakWithStatusInstruction: 804e3592 cc int 3 kd> !peb PEB at 7ffd5000 InheritedAddressSpace: No ReadImageFileExecOptions: No BeingDebugged: No ImageBaseAddress: 00400000 Ldr 00191e90 Ldr.Initialized: Yes Ldr.InInitializationOrderModuleList: 00191f28 . 00192258 Ldr.InLoadOrderModuleList: 00191ec0 . 001922e8 Ldr.InMemoryOrderModuleList: 00191ec8 . 001922f0 Base TimeStamp Module 400000 3b6a692f Aug 03 11:04:47 2001 C:\mdl\instdrv.exe 7c910000 41109627 Aug 04 09:54:15 2004 C:\WINDOWS\system32\ntdll.dll 7c800000 46239be7 Apr 16 17:53:11 2007 C:\WINDOWS\system32\kernel32.dll 77da0000 411095e8 Aug 04 09:53:12 2004 C:\WINDOWS\system32\ADVAPI32.dll 77e50000 46923412 Jul 09 15:11:46 2007 C:\WINDOWS\system32\RPCRT4.dll 77fc0000 4110961d Aug 04 09:54:05 2004 C:\WINDOWS\system32\Secur32.dll 7e390000 45f02dce Mar 08 16:37:50 2007 C:\WINDOWS\system32\USER32.dll 77ef0000 4677dae9 Jun 19 15:32:25 2007 C:\WINDOWS\system32\GDI32.dll SubSystemData: 00000000 ProcessHeap: 00080000 ProcessParameters: 00020000 WindowTitle: 'C:\mdl\instdrv.exe' ImageFile: 'C:\mdl\instdrv.exe' CommandLine: '"C:\mdl\instdrv.exe" ' DllPath: 'C:\mdl;C:\WINDOWS\system32;C:\WINDOWS\system;C:\WINDOWS;.;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem' Environment: 00010000 ALLUSERSPROFILE=C:\Documents and Settings\All Users APPDATA=C:\Documents and Settings\fu\Application Data CLIENTNAME=Console CommonProgramFiles=C:\Program Files\Fichiers communs COMPUTERNAME=FU ComSpec=C:\WINDOWS\system32\cmd.exe FP_NO_HOST_CHECK=NO HOMEDRIVE=C: HOMEPATH=\Documents and Settings\fu LOGONSERVER=\\FU NUMBER_OF_PROCESSORS=1 OS=Windows_NT Path=C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem PATHEXT=.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH PROCESSOR_ARCHITECTURE=x86 PROCESSOR_IDENTIFIER=x86 Family 15 Model 72 Stepping 2, AuthenticAMD PROCESSOR_LEVEL=15 PROCESSOR_REVISION=4802 ProgramFiles=C:\Program Files SESSIONNAME=Console SystemDrive=C: SystemRoot=C:\WINDOWS TEMP=C:\DOCUME~1\fu\LOCALS~1\Temp TMP=C:\DOCUME~1\fu\LOCALS~1\Temp USERDOMAIN=FU USERNAME=fu USERPROFILE=C:\Documents and Settings\fu windir=C:\WINDOWS _NT_SYMBOL_PATH=SRV*C:\Symbols*http://msdl.microsoft.com/download/symbols
Ok on peut voir que le tableau de PDEs de se process se trouve à l’adresse physique 0x01d62000 en regardant le registre cr3.
kd> r cr3 cr3=01d62000
La table des PDEs se trouve donc en à l’adresse physique 0x01d62000 :
kd> !dd 01d62000l 400 # 1d62000 0ade4067 0699a067 00000000 00000000 # 1d62010 00000000 00000000 00000000 00000000 # 1d62020 00000000 00000000 00000000 00000000 # 1d62030 00000000 00000000 00000000 00000000 # 1d62040 00000000 00000000 00000000 00000000 # 1d62050 00000000 00000000 00000000 00000000 # 1d62060 00000000 00000000 00000000 00000000 # 1d62070 00000000 00000000 00000000 00000000 [...]
On la retrouve bien à l’adresse virtuelle 0xC0300000 :
kd> dd 0xC0300000 l 400 c0300000 0ade4067 0699a067 00000000 00000000 c0300010 00000000 00000000 00000000 00000000 c0300020 00000000 00000000 00000000 00000000 c0300030 00000000 00000000 00000000 00000000 c0300040 00000000 00000000 00000000 00000000 c0300050 00000000 00000000 00000000 00000000 c0300060 00000000 00000000 00000000 00000000 c0300070 00000000 00000000 00000000 00000000 [...]
Maintenant je prends la DLL user32.dll qui commence à l’adresse virtuelle 0x7e390000 :
kd> db 7e390000 7e390000 4d 5a 90 00 03 00 00 00-04 00 00 00 ff ff 00 00 MZ.............. 7e390010 b8 00 00 00 00 00 00 00-40 00 00 00 00 00 00 00 ........@....... 7e390020 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 7e390030 00 00 00 00 00 00 00 00-00 00 00 00 d8 00 00 00 ................ 7e390040 0e 1f ba 0e 00 b4 09 cd-21 b8 01 4c cd 21 54 68 ........!..L.!Th 7e390050 69 73 20 70 72 6f 67 72-61 6d 20 63 61 6e 6e 6f is program canno 7e390060 74 20 62 65 20 72 75 6e-20 69 6e 20 44 4f 53 20 t be run in DOS 7e390070 6d 6f 64 65 2e 0d 0d 0a-24 00 00 00 00 00 00 00 mode....$......
Ok PE Header classique. On va retrouver l’adresse physique correspondant à 0x7e390000. C’est partit, d’abord on calcul l’indice du PDE :
PDE kd> ? 7e390000 >> 16 Evaluate expression: 504 = 000001f8
Ok il est à l’indice 0x1F8 dans le tableau. Pour afficher son contenu on a 2 choix, soit on utilise l’addresse virtuelle C0300000 soit l’adresse physique 0x01d6200 (la commande !dd affiche le contenu à l’adresse phys passée en argument) :
kd> dd C0300000+1f8*4 l 1 c03007e0 07ed7067 kd> !dd 0x01d62000+1f8*4 l 1 # 1d627e0 07ed7067
Ok on a le PDE. La suite, trouvé le PTE, on prend l’adresse 0x7e390000 et on extrait l’indice du PTE :
< PTE kd> ? (7e390000 & 3FF000)>>C Evaluate expression: 912 = 00000390
Le PTE se trouve à l’indice 0×390. Grâce au PDE on connait l’adresse physique de la table des PTEs (7ed7*1000), il suffit de faire l’opération suivante pour connaître le contenu du PTE :
kd> !dd (7ed7*1000)+390*4 l 1 # 7ed7e40 078e8025
On y est presque, pour ceux qui on survécu la délivrance est proche ! Le champ Page Base Address du PTE nous indique l’indice de la page physique qui contient nos données. Il suffit donc de faire (PTE.Page_Base_Address)*PAGE_SIZE+Offset pour retrouver nos datas (ici l’offset est nul) :
kd> !db 78e8*1000 # 78e8000 4d 5a 90 00 03 00 00 00-04 00 00 00 ff ff 00 00 MZ.............. # 78e8010 b8 00 00 00 00 00 00 00-40 00 00 00 00 00 00 00 ........@....... # 78e8020 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ # 78e8030 00 00 00 00 00 00 00 00-00 00 00 00 d8 00 00 00 ................ # 78e8040 0e 1f ba 0e 00 b4 09 cd-21 b8 01 4c cd 21 54 68 ........!..L.!Th # 78e8050 69 73 20 70 72 6f 67 72-61 6d 20 63 61 6e 6e 6f is program canno # 78e8060 74 20 62 65 20 72 75 6e-20 69 6e 20 44 4f 53 20 t be run in DOS # 78e8070 6d 6f 64 65 2e 0d 0d 0a-24 00 00 00 00 00 00 00 mode....$.......
Wootz on retrouve notre en-tête PE de user32.dll.
Vous ne inquietez pas, il existe des commandes fournit par le kernel debuggger pour retrouver l’indice de la page physique correspond à notre adresse virtuelle. Par exemple, il y a la commande !pte :
kd> !pte 7e390000 (user32.dll) VA 7e390000 PDE at C03007E0 PTE at C01F8E40 contains 07ED7067 contains 078E8025 pfn 7ed7 ---DA--UWEV pfn 78e8 ----A--UREV
Et la commande !vtop :
kd> !vtop 0 7e390000 Pdi 1f8 Pti 390 7e390000 078e8000 pfn(078e8)
Plus d’aide je vous laisse lire l’aide de Windbg sur le sujet.
Revenons à notre problème. Je veux utiliser la page disponible à l’adresse virtuelle 0x7fff0000, comment faire ? Simple, ajouté un PTE au bon endroit :] exemple avec calc.exe
kd> !process 0 0 [...] PROCESS ffba2030 SessionId: 0 Cid: 0104 Peb: 7ffd5000 ParentCid: 03c0 DirBase: 00246000 ObjectTable: e15b1f30 HandleCount: 25. Image: calc.exe kd> .process /i ffba2030 You need to continue execution (press 'g') for the context to be switched. When the debugger breaks in again, you will be in the new process context. kd> g Break instruction exception - code 80000003 (first chance) nt!RtlpBreakWithStatusInstruction: 804e3592 cc int 3 kd> db 7fff0000 7fff0000 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ???????????????? 7fff0010 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ???????????????? 7fff0020 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ???????????????? 7fff0030 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ???????????????? 7fff0040 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ???????????????? 7fff0050 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ???????????????? 7fff0060 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ???????????????? 7fff0070 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ????????????????
On voit bien que la page 0x7fff0000 est invalide. Si on regarde son PTE on peut voir :
kd> !pte 0x7fff0000 VA 7fff0000 PDE at C03007FC PTE at C01FFFC0 contains 0079C067 contains 00000000 pfn 79c ---DA--UWEV
Le PTE n’est pas présent, il n’y donc pas de pages physiques référençant cette zone mémoire. Ce que veux dire qu’un simple mov eax, dword ptr [0x7FFF000] nous générera une exception. Maintenant je regarde le PTE qui référence l’ImageBase de calc.exe
kd> !pte 1000000 (calc.exe ImageBase) VA 01000000 PDE at C0300010 PTE at C0004000 contains 0024E067 contains 0C60C025 pfn 24e ---DA--UWEV pfn c60c ----A--UREV
Le PTE est présent, normal, je copie son contenu à l’adresse virtuelle 0xC01FFFC0 qui contient la valeur du PTE pour l’adresse virtuelle 0x7fff0000.
kd> ed C01FFFC0 0C60C025 kd> db 7fff0000 7fff0000 4d 5a 90 00 03 00 00 00-04 00 00 00 ff ff 00 00 MZ.............. 7fff0010 b8 00 00 00 00 00 00 00-40 00 00 00 00 00 00 00 ........@....... 7fff0020 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 7fff0030 00 00 00 00 00 00 00 00-00 00 00 00 f0 00 00 00 ................ 7fff0040 0e 1f ba 0e 00 b4 09 cd-21 b8 01 4c cd 21 54 68 ........!..L.!Th 7fff0050 69 73 20 70 72 6f 67 72-61 6d 20 63 61 6e 6e 6f is program canno 7fff0060 74 20 62 65 20 72 75 6e-20 69 6e 20 44 4f 53 20 t be run in DOS 7fff0070 6d 6f 64 65 2e 0d 0d 0a-24 00 00 00 00 00 00 00 mode....$.......
Ho le joli mapping :]. J’ai mappé la page qui contient le PE header de calc.exe à la l’adresse virtuelle 0x7fff0000, c’est pas beau ca ! Juste pour être sur, j’attache olly sur le calc.exe et je le lance l’instruction MOV EAX,DWORD PTR DS:[7FFF0000], hoo pas d’exception, eax contient bien 0x00905A4D, youpilol !
Bien évident faire cette opération from scratch sous KD ce n’est pas vraiment conseillé, néanmoins ca montre que c’est possible. Je vais essayer d’implémenter cela dans mon driver et je releaserais le code plus tard.
Grâce à cette technique on a pu voir qu’il est possible de profiter de le page mémoire se trouvant à la plus haute adresse user-land. Après libre à nous d’y mettre ce qu’on veut. En le faisant de cette manière on profite du fait que les VADs (Virtual Address Descriptors) décrivant l’utilisation de l’espace mémoire de notre process ne sont pas mis à jour ce qui rend cette zone mémoire invisible aux API comme NtQueryVirtualMemory. Pour savoir que la page est présente il faut y accéder.
Pendant que j’y suis je voudrais rappeler l’existence de la technique du Shadow Walker qui consiste en gros à faire croire qu’une page est swappée sur le disque quand on tente d’y accéder. Après si c’est une lecture/écriture on dirige la requête vers une page « clean ». Je vous laisse lire l’article de phrack à ce sujet puis l’article/code d’un pote, b0l0k qui je trouve n’a pas eu le succès escompté.
J’essaierais d’y revenir plus tard dessus. En attendant j’espère que vous avez apprécié l’idée de jouer avec la page perdue !
ref :
Address Tanslation
http://book.itzero.com/read/microsoft/0507/microsoft.press.microsoft.windows.internals.fourth.edition.dec.2004.internal.fixed.ebook-ddu_html/0735619174/ch07lev1sec5.html
Intel Manuals, Windows Internals, google et autres …
Entry Filed under: RE
14 Comments
1. mxatone | novembre 12th, 2007 at 15:40
En faite le probleme de ta technique c que si tu mappes une page writeable a cet endroit, tu va rendre le système vulnérable à toutes les attaques userland.
Voici comment NtWriteVirtualMemory check un pointeur :
Dump de NtWriteVirtualMemory():
and [ebp+ms_exc.disabled], 0
mov eax, _MmUserProbeAddress
cmp ebx, eax
jnb loc_5257A0
loc_505FD0:
mov eax, [ebx]
[..]
loc_5257A0: ; le mauvais cas ou l’adresse pointe dans le kernel space
mov dword ptr [eax], 0
jmp loc_505FD0
kd> dd nt!MmUserProbeAddress L 1
80557bb4 7fff0000
Quand on regardes ca, on comprend d’abord pas vraiment pourquoi dans le mauvais cas il essaie d’ecrire 0 a MmUserProbeAddress et continue …
C’est tout simplement pour lever une exception catch plus loin (pour return un status d’access denied).
Alors si la page en question est writeable, l’exception n’est pas leve et on peut ecrire en ring0 … on imagine la suite facilement ;).
Donc okay mais attention, pas writeable.
2. texane | novembre 12th, 2007 at 17:17
Salut,
Pour shadow Walker, la technique me plaisait pas mal aussi (apres avoir lu le dernier MISC d ailleurs) et j avais commence a coder un truc (ca marchouille pas top, mais au moins y a une base): https://blog.kaneton.org/bin/view/Blog/Articles
Plus precisement la technique de shadow walker consiste a desynchro les tlbs en fonction de l operation d acces a la memoire. Ca tue bien mais y a quand mm qques soucis.
Aussi pour le coup d ajouter un mapping a la main, fais gaf aux PDEs qui contiennent des entrees mappant directement 4Mo(donc pas de PTE, les larges pages), sinon tu vas canner le systeme.
3. newsoft | novembre 12th, 2007 at 21:08
Il y a aussi un vieux PoC appelé CRCVert :
http://www.vinay-mahadik.info/ReverseEngineering/crcVert/
Je cross-poste chez b0l0k
4. newsoft | novembre 12th, 2007 at 21:10
Ah non pas de cross-post, son système de commentaires est cassé
—————————–
Asirra validation failed!
ticket =
start ASIRRAVALIDATION ir=
cd ir data=
cd ir data=
start RESULT ir=1
cd ir 1 data=Fail
end Resource id #55
cd ir 0 data=
cd ir 0 data=
start DEBUG ir=
cd ir data=exceptions.Exception: invalid ticket format
end Resource id #55
cd ir 0 data=
end Resource id #55
XML:
Fail
exceptions.Exception: invalid ticket format
—————————–
5. admin | novembre 12th, 2007 at 21:57
@newsoft
Vi je connaissais, j’ai le code sur mon ordi.
@texane
J’ai regardé ton code aussi, on sent une certaine touche « linuxienne ». Je le garde, merci :]
@mxatone
Bien vu ! J’avais complétement oublié que cette page servir à généré une exception. Je voudrais juste préciser que cecelle-ci est levée uniquement si l’argument optionnel du pointeur NumberOfBytesWritten est présent. Dans ce cas il y un check :
Je pense qu’il est possible de desactiver/reactiver les protection mémoire avec VirtualProtect pour écrire rapidement dans la page (code dans une critical section) et remettre la proctection en écriture après.
6. texane | novembre 12th, 2007 at 22:28
je dirais plutot linuxien, te fie pas au pseudo
7. b0l0k | novembre 16th, 2007 at 22:59
Yo ivan,
Toujours des idées venu d’ailleurs toi, tu mange du pain perdu avec tes chocapicz pour penser a la page perdu ? =>[]
Serieusement, encore un article clair et fun. Pour shadow walker, ce qui a été dommage c’est que la technique n’a pas eu grand succes non plus.
Bon je viendrai sur IRC quand la vue d’un ordinateur ne me donnera plus des nausées
Continue comme ca
@newsoft: ah le serveur microsoft devait pas etre en forme ( c’est rare ca ! ) quand t’as essayé de post un comment. Enfin :< toute facon c’est a l’abandon !
@ la prochaine !
8. Babewn | novembre 17th, 2007 at 18:00
@ texane :
« je dirais plutot linuxien, te fie pas au pseudo »
le « ne » n’a rien a voir avec ton genre (ni meme ton nombre )
UNE touche , donc linuxienNE
un genre linuxien , une touche linuxienne
la faute aurait ete d’ecrire une touche linuxien …
@Ivanlef0u :
Bien bien mon petit.
(j’comprend rien mais ca fait leet de te feliciter avec une petite tape bienveillante dans le dos :p )
9. texane | novembre 17th, 2007 at 22:11
@Babewn: oula, on ne t a pas nourri au second degre toi… en meme temps c’est sur qu on n’est pas sur le blog de Pivot
10. Taron | novembre 17th, 2007 at 23:12
sale Gauss ?
11. Babewn | novembre 18th, 2007 at 20:58
Je n’ai en effet rien vu qui puisse se prendre au second degré
:-/
Fin bon , j’arrete de polluer le blog d’Ivanov
12. lethys | novembre 21st, 2007 at 17:54
/me déprime alors vient pourrir tes commentaires ! Je pensais trouver un pti ea games mais pour ça je suppose qu’il faudrait voir les fichiers cachés du repository …
13. Ivanlef0u’s Blog &r&hellip | février 4th, 2008 at 00:30
[...] Pour comprendre comment fonctionne la protection en non-execute des pages, il faut d’abord savoir comment fonctionne la translation d’adresses virtuelles en adresses physiques, pour cela je vous invite à relire ce post. [...]
14. Volatility : Extraction o&hellip | mai 10th, 2010 at 09:47
[...] avons une nouvelle table : classiquement nous avions sans PAE une page directory, une page table (PDE/PTE rappelez vous) et nous pouvions pointé l’octet en mémoire physique ; maintenant nous avons une page [...]
Trackback this post