ErrorInvalidParameter en CreateProcessW con EXTENDED_STARTUPINFO_PRESENT

Iniciado por nts94, 4 Junio 2012, 19:21 PM

0 Miembros y 1 Visitante están viendo este tema.

nts94

Bueeeno, he intentado ser lo más explícito posible con el tema de este post. Primero una introducción (para los que no lo sepan ya):

<INTRO>
A partir de Windows Vista se puede "elegir" el proceso padre para un nuevo proceso (siempre que se tenga permisos para abrir el proceso).
</INTRO>

Corta,ehh? xD El caso es que lo he estado probando en Windows 7 x64 y me funciona con la versión ANSI (CreateProcessA) pero no con CreateProcessW. El código que uso es éste:


       /* ... */
if(SysGetVersion() < OSV_WIN_VISTA)
{
SetLastError(ERROR_NOT_SUPPORTED);
return FALSE;
}

if(!pwzExePath || lstrlenW(pwzExePath) > MAX_PATH)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}

STARTUPINFOEXW st = { sizeof(STARTUPINFOEXW) };
GetStartupInfoW(&st.StartupInfo);

PROCESS_INFORMATION pci;

SIZE_T cbList = 0;
InitializeProcThreadAttributeList(NULL, 1, 0, &cbList);
st.lpAttributeList = (LPPROC_THREAD_ATTRIBUTE_LIST)HeapAlloc(SYS_HEAP, 0, cbList);
DBG_ASSERT(st.lpAttributeList);
InitializeProcThreadAttributeList(st.lpAttributeList, 1, 0, &cbList);
UpdateProcThreadAttribute(st.lpAttributeList, 0, PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, &hParent, sizeof(HANDLE),
NULL, NULL);

DBG_MSGBOX_TRACE_W(pwzExePath);

BOOL bRet = CreateProcessW(NULL, L"C:\\Windows\\system32\\cmd.exe" /*pwzExePath*/, NULL, NULL, FALSE, EXTENDED_STARTUPINFO_PRESENT,
                                        NULL, NULL, &st.StartupInfo, &pci);

DeleteProcThreadAttributeList(st.lpAttributeList);
HeapFree(SYS_HEAP, 0, st.lpAttributeList);

if(bRet)
{
DBG_MSGBOX_TRACE("No error");
CloseHandle(pci.hProcess);
CloseHandle(pci.hThread);
}
else
DBG_MSGBOX_TRACE("Error");

return bRet;


Nota: supongo que debe de ser algo relacionado con la especificacion del tamaño de las estructuras, pero como todavía no hay un ollydbg para x64 y no me aclaro con el windbg (y se cuelga mucho, no se si solo me pasa a mi), no he podido debuggearlo

Karcrack

Para evitar problemas con los cambios de UNICODE a ANSI y viceversa no deberías especificar ninguna y luego definir la directiva correspondiente para el compilador. Ej:


#undef UNICODE
void main(){
  MessageBox(0,_T("PRUEBA"),_T("LOL"),0);
}

Esto te generará una versión ANSI funcional, y si en lugar de desdefinir "UNICODE" lo defines (por defecto está ya definido) te generará la versión UNICODE. Igual con las estructuras, si no defines A/W el compilador automáticamente hará el trabajo.

nts94

Ya, el problema es que no se trata de un ejecutable sino de una DLL, y quiero poder usar ambas versiones (como la api de windows) de manera que exporto dos funciones tal que:


extern "C" {
/* ... */
BOOL SysCreateProcessByParentA(const PSTR pszExePath, HANDLE hParent);
BOOL SysCreateProcessByParentW(const PWSTR pwzExePath, HANDLE hParent);
/* ... */
}

#ifdef _UNICODE
# define SysCreateProcessByParent SysCreateProcessByParentW
#else
# define SysCreateProcessByParent SysCreateProcessByParentA
#endif


La version anterior era la UNICODE. La versión ANSI solo convierte los parametros a UNICODE y llama a la version UNICODE. De todas formas, gracias  :D

Karcrack

Yo en el código no veo nada raro, pero siempre puedes compilar a 32bits y debuggear con el Olly si te aclaras con éste mejor.

Saludos

nts94

Ok, después de unas cuantas (muchas) horas lo encontré: resulta que los de Microsoft todavía no han solucionado el famoso bug de CreateProcessW, y al intentar escribir sobre mi string directamente (es decir, sin buffer intermedio, el string estaría en una pagina de solo lectura) el programa petaba (por eso CreateProcessA sí que iba), y a veces petaba y a veces daba error porque al intentarlo en la de x86, no me dejaba inyectarme en sysprep.exe, saltarme el UAC, conseguir el SeDebugPrivilege y claro, el handle a winlogon.exe era inválido (por algo lo he puesto en la sección de malware) xD

En fin, gracias Karcrack por la ayuda. TEMA SOLUCIONADO