APC
avril 1st, 2007 at 01:42 admin
Toujours en quête d’idées folles je suis tombé sur un truc funny en lisant le SDK, c’est marrant de se dire que tout le monde utilise cette fonctionnalité pour faire des choses « utiles » alors que moi je la détourne dans le but d’avancer mon projet personnel intitulé « CONQUERIR LE MONDE OU RIEN ! »
Il s’agit juste d’une technique d’injection de code Userland dont le principal intérêt est qu’on ne sait pas vraiment quand notre code sera exécuté :]
Les APC (Asynchronous Procedure Calls) permettent d’interrompre l’exécution d’un thread, si celui-ci l’autorise, pour pouvoir exécuté une routine. La chose est simple, on copie dans l’espace mémoire du process notre routine et on l’a met en file d’attente avec la fonction QueueUserAPC() puis on attend (environ 5 mins au micro-ondes). Pour lancer cette routine le thread doit passer dans un état dit « Alertable », il ne le fait que si le paramètre bAlertable des API suivantes est mit à vrai :
SleepEx, SignalObjectAndWait, WaitForSingleObjectEx, WaitForMultipleObjectsEx, MsgWaitForMultipleObjectsEx
Clairement notre procédure mise en attente à peu de chance d’être lancer immédiatement, pour avoir plus de chance on la met en file d’attente sur tout les thread du process. Je l’ai testé sur le Notepad et c’est quand je fais Fichier->Ouvrir que ma procédure injectée est lancé, surement à cause de l’appel à GetOpenFileName() qui load le menu pour choisir le fichier à ouvrir.
Après avoir mit un BP sur l’API native ZwWaitForSingleObject dans ntdll et tracer le notepad, j’arrive à la call stack :
Call stack of main thread Address Stack Procedure / arguments Called from Frame 0007D2B0 77E60ACB ? kernel32.WaitForSingleObjectEx RPCRT4.77E60AC5 0007D2B4 00000131 hObject = 00000131 0007D2B8 000DBBA0 Timeout = 900000. ms 0007D2BC 00000001 fAlertable = TRUE <--W00T 0007D2CC 77E60A81 ? RPCRT4.77E60AA9 RPCRT4.77E60A7C 0007D2F0 77E652C7 RPCRT4.77E60A64 RPCRT4.77E652C2 0007D2EC 0007D318 77E6520D Includes RPCRT4.77E652C7 RPCRT4.77E6520A 0007D314 0007D338 77E6565F RPCRT4.77E60833 RPCRT4.77E6565A 0007D334 0007D440 77E653ED RPCRT4.77E6553D RPCRT4.77E653E8 0007D43C 0007D488 77E64CF6 RPCRT4.77E65372 RPCRT4.77E64CF1 0007D484 0007D4D8 77E64E0D ? RPCRT4.77E64BEB RPCRT4.77E64E08 0007D4D4 0007D51C 77E64D5C ? RPCRT4.77E64D85 RPCRT4.77E64D57 0007D518 0007D580 77E600AC RPCRT4.77E600DC RPCRT4.77E600A7 0007D57C 0007D5B0 77E58DC9 Includes RPCRT4.77E600AC RPCRT4.77E58DC6 0007D5AC 0007D5C8 77E58E00 RPCRT4.I_RpcGetBufferWithObject RPCRT4.77E58DFB 0007D5C4 0007D5D8 77E5942D RPCRT4.I_RpcGetBuffer RPCRT4.77E59428 0007D5D4 0007D5E8 77ED360B ? RPCRT4.NdrGetBuffer RPCRT4.77ED3606 0007D5E4 0007D9C8 77DB1CD0 ?ADVAPI32.77DB1CCB 0007D9C4 0007D9DC 77DB1C52 ADVAPI32.77DB1CB5 ADVAPI32.77DB1C4D 0007D9D8 0007DA30 77DCCB54 ? ADVAPI32.LsaOpenPolicy ADVAPI32.77DCCB4F 0007DA2C 0007DA84 778E8FEB Includes ADVAPI32.77DCCB54 778E8FE9 0007DA80 0007DAA4 778EA005 778EA091 778EA000 0007DAA0 0007DAD4 778E9068 ? 778E9FE8 778E9063 0007DAD0 0007DB18 7CA0F5AE ? 778E902D SHELL32.7CA0F5A8 0007DB14 0007DB98 7CA0F54C SHELL32.7CA0F581 SHELL32.7CA0F547 0007DB94 0007DBB0 7CA0F425 SHELL32.7CA0F4FB SHELL32.7CA0F420 0007DBAC 0007DBD0 7CA0F4F1 SHELL32.7CA0F3D9 SHELL32.7CA0F4EC 0007DBCC 0007DBF8 7C9FA276 SHELL32.7C9FA29D SHELL32.7C9FA271 0007DBF4 0007DC14 7CA00019 SHELL32.7C9FA230 SHELL32.7CA00014 0007DC10 0007DC48 7C9FDF0F SHELL32.7C9FE3E1 SHELL32.7C9FDF0A 0007DC44 0007DCAC 7C9FDE50 Includes SHELL32.7C9FDF0F SHELL32.7C9FDE4D 0007DCA8 0007DD14 7C9FE07B Includes SHELL32.7C9FDE50 SHELL32.7C9FE078 0007DD10 0007DD3C 7C9FE019 SHELL32.7C9FE059 SHELL32.7C9FE014 0007DD38
Là notre APC sera exécuté car le thread va devenir Alertable.
Ha on me dit dans l’oreillette qu’on y comprend rien, éclaircissons tout cela
C:\ProgHack\c>StackWatcher notepad.exe Thread ID : 2232 0x77e60a64 : RPCRT4!UTIL_GetOverlappedResultEx+0x1d 0x77e65263 : RPCRT4!CO_SyncRecv+0x71 0x77e60833 : RPCRT4!OSF_CCONNECTION::TransSendReceive+0x9d 0x77e6553d : RPCRT4!OSF_CCONNECTION::SendBindPacket+0x575 0x77e65372 : RPCRT4!OSF_CCONNECTION::ActuallyDoBinding+0xa6 0x77e64beb : RPCRT4!OSF_CCONNECTION::OpenConnectionAndBind+0x20f 0x77e64d85 : RPCRT4!OSF_CCALL::BindToServer+0xed 0x77e600dc : RPCRT4!OSF_BINDING_HANDLE::AllocateCCall+0x2b0 0x77e60084 : RPCRT4!OSF_BINDING_HANDLE::NegotiateTransferSyntax+0x28 0x77e58d81 : RPCRT4!I_RpcGetBufferWithObject+0x5b 0x77e58df1 : RPCRT4!I_RpcGetBuffer+0xf 0x77e59405 : RPCRT4!NdrGetBuffer+0x28 0x77ed34d0 : RPCRT4!NdrClientCall2+0x195 0x77db1cb5 : ADVAPI32!LsarOpenPolicy2+0x1b 0x77db1c0f : ADVAPI32!LsaOpenPolicy+0x95 0x77dccaf6 : ADVAPI32!LookupPrivilegeValueW+0x66 0x778ea091 : SETUPAPI!EnablePnPPrivileges+0x2d 0x778e9fe8 : SETUPAPI!PnPGetGlobalHandles+0x1d 0x778e902d : SETUPAPI!CM_Get_Device_Interface_List_Size_ExW+0x45 0x7ca0f581 : SHELL32!CMountPoint::_EnumVolumes+0xc5 0x7ca0f4fb : SHELL32!CMountPoint::_InitLocalDriveHelper+0x52 0x7ca0f3d9 : SHELL32!CMountPoint::_InitLocalDrives+0xc8 0x7c9fa29d : SHELL32!CMountPoint::_GetMountPointDL+0x48 0x7c9fa230 : SHELL32!CMountPoint::GetMountPoint+0x46 0x7c9fe3e1 : SHELL32!CDrivesFolder::_FillIDDrive+0x5c 0x7c9fde70 : SHELL32!CDrivesFolder::ParseDisplayName+0x9f 0x7c9fdddf : SHELL32!CRegFolder::ParseDisplayName+0x93 0x7c9fe059 : SHELL32!CDesktopFolder::_ChildParseDisplayName+0x22 0x7c9fdf96 : SHELL32!CDesktopFolder::ParseDisplayName+0x7e 0x7c9fdddf : SHELL32!CRegFolder::ParseDisplayName+0x93 0x7c9fdd09 : SHELL32!SHParseDisplayName+0xa3 0x7c9fe2f9 : SHELL32!ILCreateFromPathEx+0x3d 0x7ca01b98 : SHELL32!_CreateFolderIDList+0x102 0x7c9ff293 : SHELL32!_GetFolderIDListCached+0x84 0x7c9ff3ed : SHELL32!SHGetFolderLocation+0x9e 0x7c9ff46f : SHELL32!SHGetSpecialFolderLocation+0x17 0x7634545c : comdlg32!CFileOpenBrowser::InitLookIn+0x51 0x763436d1 : comdlg32!InitLocation+0x102 0x763425e4 : comdlg32!OpenDlgProc+0x3af 0x77d1870c : USER32!InternalCallWinProc+0x28 0x77d240d8 : USER32!UserCallDlgProcCheckWow+0x146 0x77d23f5a : USER32!DefDlgProcWorker+0xa8 0x77d1b7d3 : USER32!SendMessageWorker+0x448 0x77d24956 : USER32!InternalCreateDialog+0x9df 0x77d26110 : USER32!InternalDialogBox+0xa9 0x77d261d2 : USER32!DialogBoxIndirectParamAorW+0x37 0x77d32043 : USER32!DialogBoxIndirectParamW+0x1b 0x763433ee : comdlg32!NewGetFileName+0x240 0x763433d6 : comdlg32!NewGetOpenFileName+0xf 0x76343324 : comdlg32!GetFileName+0x35d 0x76357c65 : comdlg32!GetOpenFileNameW+0x62 <---LOL ! 0x1002b87 : notepad!NPCommand+0x202 0x1003429 : notepad!NPWndProc+0x4fe 0x77d1870c : USER32!InternalCallWinProc+0x28 0x77d1875f : USER32!UserCallWinProcCheckWow+0x150 0x77d188f1 : USER32!DispatchMessageWorker+0x306 0x77d18a01 : USER32!DispatchMessageW+0xf 0x1002936 : notepad!WinMain+0xdc 0x100739d : notepad!WinMainCRTStartup+0x174
Ha c’est beaucoup mieux, si on regarde dans RPC4CRT.dll à la fonction CO_SyncRecv :
push [ebp+dwMilliseconds] ; dwMilliseconds lea eax, [ebp+arg_0] push 1 ; bAlertable <-- W00T :} push eax ; int lea eax, [esi+34h] push eax ; int push esi ; int call ?UTIL_GetOverlappedResultEx@@YGJPAXPAU_OVERLAPPED@@PAKHK@Z
Je rappel juste pour ceux dont le cerveau aurait BSOD que c’est la fonction GetOpenFileNameW qui est appelé quand on fait Fichier->Ouvrir :p
Bref une technique marrante qui à l’avantage de ne pas crée de nouveau thread. De plus si le thread visé tourne avec des privilèges supérieur alors votre routine, si elle est lancée, les aura aussi :]
Le code/binaire ici :
http://ivanlef0u.fr/repo/APC.rar
Enjoy !
ps : Ce post n’est pas un toto d’avril :p
Entry Filed under: Non classé
Trackback this post