CreateProcess

janvier 19th, 2008 at 01:29 admin

Hum, un post un peu forcé, histoire de poser quelque chose sur ce blog. J’avoue que sur ce coup je suis un peu décu de mon taff. Bref, un échec ne peut qu’être enrichissant … Je me suis lancé dans l’idée de coder ma propre fonction CreateProcess afin de réaliser une attaque précise, malheureusement j’ai rencontré 2 gros problèmes.. :(


D’abord pour ce mettre dans l’ambiance, on va s’écouter du Burzum, ca aide à décrasser le cerveau.
Burzum – JesusTod

La création d’un processus n’est pas si compliqué que ca. Tout d’abord il nous faut un joli binaire, on commence gentiment en l’ouvrant avec CreateFile puis on lui associe un objet section avec l’API CreateFileMapping avec l’attribut SEC_IMAGE. Cet attribut permet de dire à l’API quelle représente une image exécutable afin que l’API nous fabrique une structure SECTION_IMAGE_INFORMATION dessus, nous verrons son utilité par la suite. Dans le code suivant j’utilise directement les API natives, j’avais envie de me prendre la tête :)

InitializeObjectAttributes(&ObjectAttributes, &usPath, OBJ_CASE_INSENSITIVE, NULL, NULL);

//ouvre le fichier binaire
Status=ZwOpenFile(&hFile,
				FILE_EXECUTE|SYNCHRONIZE,
				&ObjectAttributes,
				&IoBlock,
				FILE_SHARE_READ,
				FILE_SYNCHRONOUS_IO_NONALERT);
if(!NT_SUCCESS(Status))
{
	printf("Error with ZwOpenFile : 0x%x\n", Status);
	goto end;
}

InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL);
//cree l'objet section avec l'attribut SEC_IMAGE specifique au executable images.
Status=ZwCreateSection(&hSection,
					SECTION_ALL_ACCESS,
					&ObjectAttributes,
					0,
					PAGE_EXECUTE,
					SEC_IMAGE,
					hFile);
if(!NT_SUCCESS(Status))
{
	printf("Error with ZwCreateSection : 0x%x\n", Status);
	goto end;
}

Maintenant qu’on a notre handle sur la section on peut crée l’objet EPROCESS himsefl avec l’API ZwCreateProcess.

NTSTATUS
NtCreateProcess(
    __out PHANDLE ProcessHandle,
    __in ACCESS_MASK DesiredAccess,
    __in_opt POBJECT_ATTRIBUTES ObjectAttributes,
    __in HANDLE ParentProcess,
    __in BOOLEAN InheritObjectTable,
    __in_opt HANDLE SectionHandle,
    __in_opt HANDLE DebugPort,
    __in_opt HANDLE ExceptionPort
    )
Routine Description:

    This routine creates and initializes a process object.

Arguments:

    ProcessHandle - Returns the handle for the new process.

    DesiredAccess - Supplies the desired access modes to the new process.

    ObjectAttributes - Supplies the object attributes of the new process.

    ParentProcess - Supplies a handle to the process' parent process.  If this
                    parameter is not specified, then the process has no parent
                    and is created using the system address space.

    Flags         - Process creation flags

    SectionHandle - Supplies a handle to a section object to be used to create
                    the process' address space.  If this parameter is not
                    specified, then the address space is simply a clone of the
                    parent process' address space.

    DebugPort - Supplies a handle to a port object that will be used as the
                process' debug port.

    ExceptionPort - Supplies a handle to a port object that will be used as the
                    process' exception port.

Remarquez le commentaire au niveau du SectionHandle, si jamais celui-ci est a NULL, on fabrique un fork du process courant, ce qui dans certains cas peut s’avérer utile.

Quand on appel ZwCreateProcess, le kernel se charge de mettre en place la structure EPROCESS associé avec lui en le créant avec ObCreateObject. Son espace mémoire est crée avec MmCreateProcessAddressSpace et init avec MmInitializeProcessAddressSpace.

La suite consiste à initialiser le primary du futur process. Pour cela on doit lui allouer une mémoire qui lui servira de stack. La taille de stack est retrouvé à l’aide du PE header du binaire, ce qui est cool c’est que la fonction ZwQuerySection peut nous renvoyer une structure SECTION_IMAGE_INFORMATION qui contient les valeurs suivantes :

typedef struct _SECTION_IMAGE_INFORMATION {
    PVOID TransferAddress;
    ULONG ZeroBits;
    SIZE_T MaximumStackSize;
    SIZE_T CommittedStackSize;
    ULONG SubSystemType;
    union {
        struct {
            USHORT SubSystemMinorVersion;
            USHORT SubSystemMajorVersion;
        };
        ULONG SubSystemVersion;
    };
    ULONG GpValue;
    USHORT ImageCharacteristics;
    USHORT DllCharacteristics;
    USHORT Machine;
    BOOLEAN ImageContainsCode;
    BOOLEAN Spare1;
    ULONG LoaderFlags;
    ULONG Reserved[ 2 ];
} SECTION_IMAGE_INFORMATION, *PSECTION_IMAGE_INFORMATION;

2 champs nous intéresse, CommittedStackSize et MaximumStackSize. Le premier correspond à la taille de stack à allouer obligatoirement, le second à la taille max. Sachant que le thread n’aura pas forcément besoin de toute sa stack, on va éviter le gaspillage en réservant la mémoire sur une taille de MaximumStackSize tout en utilisant physiquement que CommitedStackSize de mémoire.

Plus tard, pour crée le thread avec ZwCreateThread on va avoir besoin de lui fournir une structure INITIAL_TEB :

typedef struct _INITIAL_TEB {
    struct {
        PVOID OldStackBase;
        PVOID OldStackLimit;
    } OldInitialTeb;
    PVOID StackBase;
    PVOID StackLimit;
    PVOID StackAllocationBase;
} INITIAL_TEB, *PINITIAL_TEB;

Comme nous connaissons les besoins de la main stack, nous allons remplir cette structure. Première étape, allouer en MEM_RESERVE MaximumStackSize de mémoire avec ZwAllocateVirtualMemory dans l’espace mémoire fraichement crée. On récupère l’adresse dans le champ StackAllocationBase. Ensuite, on fabrique la pile selon le schéma suivant :

StackAllocationBase
|                 |
|    StackLimit   |
|                 |
|                 |
|    StackBase    |
+-----------------+

L'espace representé par StackAllocationBase est en MEM_RESERVE.
Celui entre StackLimit et StackBase est en MEM_COMMIT|MEM_RESERVE.

Tout l’espace de StackAllocationBase est en MEM_RESERVE, celui de l’adresse la plus haute de StackAllocationBase (Stackbase) jusqu’a Stackbase-ImageInfo.CommittedStackSize est en MEM_COMMIT|MEM_RESERVE.

Cela veut dire que physiquement on aura réservé dans la ram que CommittedStackSize de mémoire, alors que les VAD (Virtual Address Descriptors) du process décriront l’espace représenter par StackAllocationBase comme utilisé.

//recup la structure ImageInfo
Status=ZwQuerySection(hSection,
					SectionImageInformation,
					&ImageInfo,
					sizeof(ImageInfo),
					NULL);
if(!NT_SUCCESS(Status))
{
    printf("Error with ZwQuerySection : 0x%x\n", Status);
	goto end;
}

printf("ImageInfo.MaximumStackSize : 0x%x\n", ImageInfo.MaximumStackSize);
printf("ImageInfo.CommittedStackSize : 0x%x\n", ImageInfo.CommittedStackSize);

RtlZeroMemory(&InitialTeb, sizeof(InitialTeb));

//Alloue ImageInfo.MaximumStackSize et stoque l'adresse dans InitialTeb.StackAllocationBase
//les pages de sont que MEM_RESERVE
Status=ZwAllocateVirtualMemory(hProcess,
							&InitialTeb.StackAllocationBase,
							0,
							&ImageInfo.MaximumStackSize,
							MEM_RESERVE,
							PAGE_READWRITE);
if(!NT_SUCCESS(Status))
{
	printf("Error with ZwAllocateVirtualMemory (1) : 0x%x\n", Status);
	goto end;
}							

InitialTeb.StackBase=(PVOID)((ULONG)InitialTeb.StackAllocationBase+ImageInfo.MaximumStackSize);
InitialTeb.StackLimit=(PVOID)((ULONG)InitialTeb.StackBase-ImageInfo.CommittedStackSize);

n=(ULONG)(ImageInfo.CommittedStackSize);
p=(PVOID)InitialTeb.StackLimit;

//Commit les pages entre StackBase et StackLimit qui seront utilisées pour la stack
Status=ZwAllocateVirtualMemory(hProcess,
							(PVOID*)&p,
							0,
							&n,
							MEM_COMMIT,
							PAGE_READWRITE);
if(!NT_SUCCESS(Status))
{
	printf("Error with ZwAllocateVirtualMemory (2): 0x%x\n", Status);
	goto end;
}

Après tout ca, on peut tranquillement créer notre thread avec ZwCreateThread de proto :

NTSTATUS
NtCreateThread(
    __out PHANDLE ThreadHandle,
    __in ACCESS_MASK DesiredAccess,
    __in_opt POBJECT_ATTRIBUTES ObjectAttributes,
    __in HANDLE ProcessHandle,
    __out PCLIENT_ID ClientId,
    __in PCONTEXT ThreadContext,
    __in PINITIAL_TEB InitialTeb,
    __in BOOLEAN CreateSuspended
    )

/*++

Routine Description:

    This routine creates and initializes a thread object.

Arguments:

    ThreadHandle - Returns the handle for the new thread.

    DesiredAccess - Supplies the desired access modes to the new thread.

    ObjectAttributes - Supplies the object attributes of the new thread.

    ProcessHandle - Supplies a handle to the process that the thread is being
                    created within.

    ClientId - Returns the CLIENT_ID of the new thread.

    ThreadContext - Supplies a pointer to a context frame that represents the
                initial user-mode context for a user-mode thread. The absence
                of this parameter indicates that a system thread is being
                created.

    InitialTeb - Supplies the contents of certain fields for the new threads
                 TEB. This parameter is only examined if both a trap and
                 exception frame were specified.

    CreateSuspended - Supplies a value that controls whether or not a user-mode
                      thread is created in a suspended state.

--*/

Hop le code très simple qui réalise cela :

RtlZeroMemory(&Context, sizeof(CONTEXT));

//Definit le context de depart du thread

Context.SegGs=0;
Context.SegFs=0x3B; //segment fs r3
Context.SegEs=0x23; //segment de data r3
Context.SegDs=0x23;
Context.SegSs=0x23;
Context.SegCs=0x1B; //segment de code r3
Context.EFlags=0x200; // force interrupts on, clear all else.
Context.Esp=(ULONG)InitialTeb.StackBase-4;
//TransferAddress est renvoye dans la structure ImageInfo, c'est l'entrypoint de notre programme
Context.Eip=(ULONG)ImageInfo.TransferAddress;

printf("ImageInfo.TransferAddress (EntryPoint) : 0x%x\n", ImageInfo.TransferAddress);

Status=ZwCreateThread(&hThread, //ThreadHandle
					THREAD_ALL_ACCESS, //DesiredAccess
					NULL, //ObjectAttributes
					hProcess,  //ProcessHandle
					&ClientId, //ClientId,
					&Context, //ThreadContext
					&InitialTeb, //InitialTeb
					TRUE); //CreateSuspended
if(!NT_SUCCESS(Status))
{
	printf("Error with ZwCreateThread : 0x%x\n", Status);
	goto end;
}

Remarquez que le thread est crée en suspended. On doit faire encore une petite opération avec de la lancer.

Entre temps nous somme censés initialiser le champ ProcessParameters du PEB du futur process à l’aide de la structure RTL_USER_PROCESS_PARAMETERS et de l’API RtlCreateProcessParameters :

typedef struct _RTL_USER_PROCESS_PARAMETERS {
    ULONG MaximumLength;
    ULONG Length;

    ULONG Flags;
    ULONG DebugFlags;

    HANDLE ConsoleHandle;
    ULONG  ConsoleFlags;
    HANDLE StandardInput;
    HANDLE StandardOutput;
    HANDLE StandardError;

    CURDIR CurrentDirectory;        // ProcessParameters
    UNICODE_STRING DllPath;         // ProcessParameters
    UNICODE_STRING ImagePathName;   // ProcessParameters
    UNICODE_STRING CommandLine;     // ProcessParameters
    PVOID Environment;              // NtAllocateVirtualMemory

    ULONG StartingX;
    ULONG StartingY;
    ULONG CountX;
    ULONG CountY;
    ULONG CountCharsX;
    ULONG CountCharsY;
    ULONG FillAttribute;

    ULONG WindowFlags;
    ULONG ShowWindowFlags;
    UNICODE_STRING WindowTitle;     // ProcessParameters
    UNICODE_STRING DesktopInfo;     // ProcessParameters
    UNICODE_STRING ShellInfo;       // ProcessParameters
    UNICODE_STRING RuntimeData;     // ProcessParameters
    RTL_DRIVE_LETTER_CURDIR CurrentDirectores[ RTL_MAX_DRIVE_LETTERS ];
} RTL_USER_PROCESS_PARAMETERS, *PRTL_USER_PROCESS_PARAMETERS;

extern "C"
NTSYSAPI
NTSTATUS
NTAPI
RtlCreateProcessParameters(
    PRTL_USER_PROCESS_PARAMETERS *ProcessParameters,
    PUNICODE_STRING ImagePathName,
    PUNICODE_STRING DllPath,
    PUNICODE_STRING CurrentDirectory,
    PUNICODE_STRING CommandLine,
    PVOID Environment,
    PUNICODE_STRING WindowTitle,
    PUNICODE_STRING DesktopInfo,
    PUNICODE_STRING ShellInfo,
    PUNICODE_STRING RuntimeData
    );

On retrouve un peu la même structure que celle de PROCESS_INFORMATION qu’on fournit en entrée à CreateProcess. Pour init le PEB on utilise le code suivant :

VOID CreateProcessParameters(HANDLE hProcess, PPEB Peb, PUNICODE_STRING ImageFile)
{
	ULONG n;
	PVOID p;
	NTSTATUS Status;
	PRTL_USER_PROCESS_PARAMETERS pp;

	Status=RtlCreateProcessParameters(&pp, ImageFile, 0, 0, 0, 0, 0, 0, 0, 0);
	if(!NT_SUCCESS(Status))
	{
		printf("Error with RtlCreateProcessParameters : 0x%x\n", Status);
		return;
	} 

	pp->Environment=CopyEnvironment(hProcess);

	n=pp->MaximumLength;
	p=0;

	//alloue l'espace pour la structure RTL_USER_PROCESS_PARAMETERS
	Status=ZwAllocateVirtualMemory(hProcess, &p, 0, &n, MEM_COMMIT, PAGE_READWRITE);
	if(!NT_SUCCESS(Status))
	{
		printf("Error with ZwAllocateVirtualMemory : 0x%x\n", Status);
		return;
	}

	//copie la structure dans l'espace memoire du process
	Status=ZwWriteVirtualMemory(hProcess, p, pp, pp->MaximumLength, 0);
	if(!NT_SUCCESS(Status))
	{
		printf("Error with ZwWriteVirtualMemory : 0x%x\n", Status);
		return;
	}

	//met a jour le champ du PEB
	Status=ZwWriteVirtualMemory(hProcess, (PCHAR)Peb + 0x10, &p, sizeof(p), 0);
	if(!NT_SUCCESS(Status))
	{
		printf("Error with ZwWriteVirtualMemory : 0x%x\n", Status);
		return;
	}

	Status=RtlDestroyProcessParameters(pp);
}

Enfin il reste la partie la plus mystérieuse, informé le subsystem à travers le LPC \Windows\ApiPort du process csrss.exe. Je vous avouerais que c’est la partie la moins documentée, qui, de ce fait, pose le plus de problème. D’après ce que j’ai pu récupérer, on aurait un code dans ce style là :

typedef struct _CSR_CAPTURE_HEADER {
    ULONG Length;
    PCSR_CAPTURE_HEADER RelatedCaptureBuffer;
    ULONG CountMessagePointers;
    PCHAR FreeSpace;
    ULONG_PTR MessagePointerOffsets[1]; // Offsets within CSR_API_MSG of pointers
} CSR_CAPTURE_HEADER, *PCSR_CAPTURE_HEADER;

typedef ULONG CSR_API_NUMBER;

typedef struct _PBASE_CREATEPROCESS_MSG {
	HANDLE hProcess;
	HANDLE hThread;
	DWORD dwProcessId;
	DWORD dwThreadId;
	DWORD CreationFlags;
	CLIENT_ID DebuggerClientId;
	DWORD VdmBinaryType;
}BASE_CREATEPROCESS_MSG ,*PBASE_CREATEPROCESS_MSG;

typedef struct _BASE_API_MSG {
    PORT_MESSAGE h;
    PCSR_CAPTURE_HEADER CaptureBuffer;
    CSR_API_NUMBER ApiNumber;
    ULONG ReturnValue;
    ULONG Reserved;
    union {
        BASE_CREATEPROCESS_MSG CreateProcess;
    } u;
} BASE_API_MSG, *PBASE_API_MSG;

VOID InformCsrss(HANDLE hProcess, HANDLE hThread, ULONG pid, ULONG tid)
{
	NTSTATUS Status;
	BASE_API_MSG m;
    PBASE_CREATEPROCESS_MSG a=(PBASE_CREATEPROCESS_MSG)&m.u.CreateProcess;

	RtlZeroMemory(&m, sizeof(m));

	a->hProcess=hProcess;
	a->hThread=hThread;
	a->dwProcessId=pid;
	a->dwThreadId=tid;

	Status=CsrClientCallServer((PVOID)&m, 0, 0x10000, sizeof(*a));
	if(!NT_SUCCESS(Status))
	{
		printf("Error with CsrClientCallServer : 0x%x\n", Status);
		return;
	}
}

Hop quand ca c’est fait, il n’y a plus qu’a lancé le thread avec ResumeThread et c’est partit. Normalement …

Le code que je fournis ne marche pas à chaque fois, j’ai un peu de mal à déterminer d’ou provient le bug et je serais content si quelqu’un pouvais me donner une piste voir même la solution.

En fait, au départ, si j’ai commencé ce code, c’était dans l’optique de crée un process à partir de rien sur le disque. Je voulais uniquement crée la section depuis la mémoire d’un process « lanceur » qui aurait servit de base pour ZwCreateProcess, apparemment dès qu’on utilise l’attribut SEC_IMAGE avec ZwCreateSection, il faut obligatoirement un handle sur un fichier exécutable. De ce fait, je n’ai pas réussit à implémenter ma petite idée, tant pis :-(

Vous trouverez le code+binaire ici :
http://ivanlef0u.fr/repo/CreateProcess.rar

Sinon, pour jouer, quelques liens sur le petit monstre du moment, je veux bien sur parler du rooktit infectant le MBR Pour ceux qui s’ennuient vous pouvez même récupérer le binaire chez OffensiveComputing.
http://www2.gmer.net/mbr/
http://www.symantec.com/enterprise/security_response/weblog/2008/01/from_bootroot_to_trojanmebroot.html
http://www.microsoft.com/security/portal/Entry.aspx?name=VirTool:WinNT/Sinowal.A

Refs :

Windows Intenal, Chapter 6, Flow of CreateProcess
http://book.itzero.com/read/microsoft/0507/Microsoft.Press.Microsoft.Windows.Internals.Fourth.Edition.Dec.2004.internal.Fixed.eBook-DDU_html/0735619174/ch06lev1sec2.html

Kernel-mode backdoors for Windows NT
http://www.phrack.org/issues.html?issue=62&id=6&mode=txt

What Goes On Inside Windows 2000: Solving the Mysteries of the Loader
http://msdn.microsoft.com/msdnmag/issues/02/03/Loader/

Windows 2000 Native Api Reference
Example 6.2: Creating a Win32 Process

A catalog of NTDLL kernel mode to user mode callbacks, part 6: LdrInitializeThunk
http://www.nynaeve.net/?p=205

Entry Filed under: RE

15 Comments

  • 1. mxatone  |  janvier 19th, 2008 at 09:30

    Je pense que ton idee est fesable, apres il est vrai que comme tu ne te base pas sur une image executable pure (une section tagé comme executable), il faut que tu implementes des mecanismes toi même. Tel que le rensignement de SECTION_IMAGE_INFORMATION et biensur la relocation.

    Je n’ai jamais testé alors cet à prendre au conditionnel. Il faudrait regarder dans le noyau les checks fait, mais je pense pas que ZwCreateProcess check d’une facon ou l’autre que la section a ete taggé SEC_IMAGE.

    Tu n’as pas reussi à faire ce que tu voulais mais je trouve cet article très instructifs pour comprendre les étapes détaillés de la création d’un processus. So merci ;)


  • 2. Parano  |  janvier 19th, 2008 at 23:49

    Sa sens l’injection de code ;)


  • 3. SynApsus  |  janvier 20th, 2008 at 12:48

    Tout d’abord hello à toi Ivan !

    Ca faisait bien longtemps que j’étais hors circuit, mais bon j’ai mes rechutes.

    Je pense que tu devrais comme dit mxatone, abandonner le SEC_IMAGE qui est un peu verrouillé et coder ton moteur de chargement+relocs+IAT. ( a moins que l’IAT ne soit remplie par une autre des APIs que tu appelles )

    C’est pas très dur à faire, c’est un peu méthodique c’est tout :)

    Au pire j’ai un code à moi pr ça, mais bon l’ASM te donne des boutons non ? :D :D

    Et puis ce que tu veux charger n’étant pas stricto sensu un exécutable, l’IAT et les relocs ben euh :)

    Allez, @+ et bonne chance.

    Si tu le pousses loin ton truc pourrait devenir intéressant pour lancer des binaires de n’importe quel format : tu pourrais meme definir ton IvanPE format.


  • 4. le concombre masqué  |  janvier 21st, 2008 at 09:39

    tu pourrais meme definir ton IvanPE format.

    typedef struct _IMAGE_IVAN_HEADERS {
      DWORD Ffs;
      IMAGE_FILE_HEADER Chocapics;
      IMAGE_OPTIONAL_HEADER w00t;
    } IMAGE_IVAN_HEADERS, 
     *PIMAGE_IVAN_HEADERS;

    Je passe sur la description d’IMAGE_OPTIONAL_HEADER. On n’est pas dans la merde.


  • 5. admin  |  janvier 21st, 2008 at 11:58

    Yo,

    Merci pour vos réponses mxatone et SynApsus. J’ai regardé d’un peu plus près le comportement de ZwCreateProcess dans le cas ou on lui passe une section crée sans attribut SEC_IMAGE. Pas de chance ZwCreateProcess nous renvoie STATUS_SECTION_NOT_IMAGE (0xC0000049), ce status provient de la routine MmInitializeProcessAddressSpace. Sachant que ZwCreateSection ne supporte le flag SEC_IMAGE uniquement si il existe un handle du fichier valide. Je l’ai donc bien dmc …


  • 6. SynApsus  |  janvier 21st, 2008 at 19:59

    Et il se fait comment le check de MmInitializeProcessAddressSpace ? Tas ptetre moyen de fooler ça avec ton _IMAGE_IVAN_HEADERS nan ? :D


  • 7. admin  |  janvier 22nd, 2008 at 18:06

    SynApsus, les flags de la section sont stockés dans le kernel, dans l’objet SECTION_OBJECT.

    lkd> dt nt!_SECTION_OBJECT
       +0x000 StartingVa       : Ptr32 Void
       +0x004 EndingVa         : Ptr32 Void
       +0x008 Parent           : Ptr32 Void
       +0x00c LeftChild        : Ptr32 Void
       +0x010 RightChild       : Ptr32 Void
       +0x014 Segment          : Ptr32 _SEGMENT_OBJECT
    lkd> dt nt!_SEGMENT_OBJECT
       +0x000 BaseAddress      : Ptr32 Void
       +0x004 TotalNumberOfPtes : Uint4B
       +0x008 SizeOfSegment    : _LARGE_INTEGER
       +0x010 NonExtendedPtes  : Uint4B
       +0x014 ImageCommitment  : Uint4B
       +0x018 ControlArea      : Ptr32 _CONTROL_AREA
       +0x01c Subsection       : Ptr32 _SUBSECTION
       +0x020 LargeControlArea : Ptr32 _LARGE_CONTROL_AREA
       +0x024 MmSectionFlags   : Ptr32 _MMSECTION_FLAGS
       +0x028 MmSubSectionFlags : Ptr32 _MMSUBSECTION_FLAGS
    lkd> dt nt!_MMSECTION_FLAGS
       +0x000 BeingDeleted     : Pos 0, 1 Bit
       +0x000 BeingCreated     : Pos 1, 1 Bit
       +0x000 BeingPurged      : Pos 2, 1 Bit
       +0x000 NoModifiedWriting : Pos 3, 1 Bit
       +0x000 FailAllIo        : Pos 4, 1 Bit
       +0x000 Image            : Pos 5, 1 Bit
       +0x000 Based            : Pos 6, 1 Bit
       +0x000 File             : Pos 7, 1 Bit
       +0x000 Networked        : Pos 8, 1 Bit
       +0x000 NoCache          : Pos 9, 1 Bit
       +0x000 PhysicalMemory   : Pos 10, 1 Bit
       +0x000 CopyOnWrite      : Pos 11, 1 Bit
       +0x000 Reserve          : Pos 12, 1 Bit
       +0x000 Commit           : Pos 13, 1 Bit
       +0x000 FloppyMedia      : Pos 14, 1 Bit
       +0x000 WasPurged        : Pos 15, 1 Bit
       +0x000 UserReference    : Pos 16, 1 Bit
       +0x000 GlobalMemory     : Pos 17, 1 Bit
       +0x000 DeleteOnClose    : Pos 18, 1 Bit
       +0x000 FilePointerNull  : Pos 19, 1 Bit
       +0x000 DebugSymbolsLoaded : Pos 20, 1 Bit
       +0x000 SetMappedFileIoComplete : Pos 21, 1 Bit
       +0x000 CollidedFlush    : Pos 22, 1 Bit
       +0x000 NoChange         : Pos 23, 1 Bit
       +0x000 HadUserReference : Pos 24, 1 Bit
       +0x000 ImageMappedInSystemSpace : Pos 25, 1 Bit
       +0x000 UserWritable     : Pos 26, 1 Bit
       +0x000 Accessed         : Pos 27, 1 Bit
       +0x000 GlobalOnlyPerSession : Pos 28, 1 Bit
       +0x000 Rom              : Pos 29, 1 Bit
       +0x000 filler           : Pos 30, 2 Bits
    

    Tu vois le joli flag Image dans MMSECTION_FLAGS :p


  • 8. SynApsus  |  janvier 23rd, 2008 at 10:12

    J’imagines que tu veux pas de driver, ni chercher un bug kernel pour aller reecrire ça. Et mapper une vraie image PE en memoire, quitte à re-coller sur cet espace ben tout le code que tu veux y mettre depuis un autre fichier par exemple…


  • 9. akhenathon  |  janvier 30th, 2008 at 17:02

    Encore une fois un très bon article :)

    Je te félicite pour tout le travail que tu effectue


  • 10. martin  |  février 12th, 2008 at 07:41

    De ce que je peux voir le proc demarre bien, mais ldrpinitialize() fait une exception qui fait une exception, qui fait une exception…
    Un pb de pile ?


  • 11. admin  |  février 13th, 2008 at 10:59

    Vista, XP ?


  • 12. martin  |  février 13th, 2008 at 15:59

    Xp sp2, sorry. J’ai un peu + d’infos…
    peb/teb sont invalides d’apres windbg.
    le flag SYNCHRONIZE et FILE_READ_SHARE c’est pas trop apprecie par le SEC_IMAGE donc la section est pas mappe sur xp. Ensuite
    J’ai du supprimer le RtlCopymem ca plantait tout le temps car la section est RO de toute facon sur xp sp2 ?!
    Le getContext du thread ne fonctionne pas jai que des 0 dans les registres,c’est pas terrible.
    Sinon en mettant un brkptr avec windbg sur le retour de la livraison APC du threadcreate dans le process nouvellement cree on voit que c’est le iretd en sortant du chgt de context pour demarrer le thread qui est foireux. la pile cree pointe n’est pas bonne.
    A suivre…


  • 13. Ben  |  février 17th, 2008 at 00:51

    Very interesting article, thanks.


  • 14. barton  |  août 17th, 2008 at 15:08

    true xek!11


  • 15. broucaries  |  avril 6th, 2011 at 11:39

    Des nouvelles ? Cela m’interesse pour implementer un vrai exec sous windows ou meme un fork pour gnulib


Trackback this post


Calendar

mars 2024
L Ma Me J V S D
« fév    
 123
45678910
11121314151617
18192021222324
25262728293031

Most Recent Posts