[R] Runas en mode console

Aide et conseils concernant AutoIt et ses outils.
Règles du forum
.
highsnoop
Niveau 1
Niveau 1
Messages : 12
Enregistré le : mar. 29 nov. 2011 08:17
Status : Hors ligne

[R] Runas en mode console

#1

Message par highsnoop »

Bonjour,

J'ai un besoin d’exécuter, à partir du compte system, un script runas qui exécute une commande en tant qu'un autre compte.
exemple : runas2.exe <<account>> <<password>> <<cmd + arg>>

Pour l'instant rien de compliqué.
Mais la tache se complique en ajoutant les besoins ci-dessous :
- Afficher la sortie (sdtout+stderr) de la commande dans la console père qui exécute la commande runas
- Le code sortie du script runas doit être celui de la commande passé en argument

Essaies:
*avec la commande runas
Je récupère bien la sortie la sortie stdout+stderr mais pas le code sortie

Code : Tout sélectionner

#include <Constants.au3>

If $cmdline[0] <> "0" Then
    Local $sCmd
    $sCmd = ""
    for $i = 1 to $cmdline[0]
        ;MsgBox(0,"Valeur du parametre n°"&$cmdline[$i]," = "&$cmdline[$i])
        if $i=1 then Local $sUserName = $cmdline[$i]
        if $i=2 then Local $sPassword = $cmdline[$i]
        if $i>2 then $sCmd &= $cmdline[$i] & " "
    next
EndIf

Local $foo = RunAs($sUserName, @ComputerName, $sPassword, 1, $sCmd,@SystemDir,@SW_HIDE,$STDERR_MERGED)

if $foo=0 then
    ConsoleWrite("Error to execute " & $sCmd & " with the user " & $sUserName)
    exit 1
else

    Local $pStruct = DllStructCreate("dword")
    $ProcHandle = DllCall("kernel32.dll", "hwnd", "OpenProcess", "dword", BitOR(0x0400,0x0004,0x0001), "int", 0, "dword", $foo)
    $ProcHandle = $ProcHandle[0]
    $ProcExitCode = DllCall("kernel32.dll", "int", "GetExitCodeProcess", "hwnd", $ProcHandle, "int_ptr", DllStructGetPtr($pStruct))
    
    Local $line
    While 1
        $line = StdoutRead($foo)
        If @error Then ExitLoop
        if $line<>"" then ConsoleWrite($line)
    Wend

    While 1
        $line = StderrRead($foo)
        If @error Then ExitLoop
        if $line<>"" then ConsoleWrite("............" & $line)
    Wend

endif
exit $ProcExitCode[0]

 
*avec la commande runaswait
Je récupère bien le code sortie mais pas la sortie stdout+stderr

Code : Tout sélectionner

#include <Constants.au3>

If $cmdline[0] <> "0" Then
    Local $sCmd
    $sCmd = ""
    for $i = 1 to $cmdline[0]
        ;MsgBox(0,"Valeur du parametre n°"&$cmdline[$i]," = "&$cmdline[$i])
        if $i=1 then Local $sUserName = $cmdline[$i]
        if $i=2 then Local $sPassword = $cmdline[$i]
        if $i>2 then $sCmd &= $cmdline[$i] & " "
    next
EndIf


; Run a command prompt as the other user.
Local $pid = RunAsWait($sUserName, @ComputerName, $sPassword, 0, $sCmd , @SystemDir)

; Wait for the process to close.
ProcessWaitClose($pid)

exit $pid 
 
*avec DllCall("advapi32.dll","long","CreateProcessWithLogonW"....
Je galère un peu pour réaliser le cahier des charges :cry:

Je pense que cela doit être réalisable mais pour l'instant je n'y arrive pas
Merci de vos lumière et de votre aide
Modifié en dernier par highsnoop le ven. 02 déc. 2011 11:27, modifié 3 fois.
Avatar du membre
Tlem
Site Admin
Site Admin
Messages : 11830
Enregistré le : ven. 20 juil. 2007 21:00
Localisation : Bordeaux
Status : Hors ligne

Re: [..] Runas en mode console

#2

Message par Tlem »

Ce serait pas mal de connaitre la commande exécutée, afin que l'on puisse faire des tests !
Thierry

Rechercher sur le forum ----- Les règles du forum
Le "ça ne marche pas" est une conséquence commune découlant de beaucoup trop de raisons potentielles ...

Une idée ne peut pas appartenir à quelqu'un. (Albert Jacquard) tiré du documentaire "Copié n'est pas volé".
highsnoop
Niveau 1
Niveau 1
Messages : 12
Enregistré le : mar. 29 nov. 2011 08:17
Status : Hors ligne

Re: [..] Runas en mode console

#3

Message par highsnoop »

Je peux mettre le code mais il est en draft (plein de test et pas de resultat concluant)

Voici donc ou j'en suis
► Afficher le texte
Avatar du membre
Tlem
Site Admin
Site Admin
Messages : 11830
Enregistré le : ven. 20 juil. 2007 21:00
Localisation : Bordeaux
Status : Hors ligne

Re: [..] Runas en mode console

#4

Message par Tlem »

Super, maintenant on a deux codes plutôt complexes et on ne sais toujours pas quelles genre de commandes doivent être exécutées ! :shock:

Personnellement, je n'ai pas vraiment regardé toutes les possibilités, mais peut être que la réponse à votre question se trouve dans l'aide de la commande RunAs et plus particulièrement dans le paramètre opt_flag.
Remarks a écrit :Providing the Standard I/O parameter with the proper values permits interaction with the child process through the StderrRead, StdinWrite and StdoutRead functions. Combine the flag values (or use $STDERR_CHILD, $STDIN_CHILD & $STDOUT_CHILD, defined in Constants.au3) to manage more than one stream.
Après, il y a plein de chose à lire dans Remarks. Il faut voir. :wink:
Thierry

Rechercher sur le forum ----- Les règles du forum
Le "ça ne marche pas" est une conséquence commune découlant de beaucoup trop de raisons potentielles ...

Une idée ne peut pas appartenir à quelqu'un. (Albert Jacquard) tiré du documentaire "Copié n'est pas volé".
highsnoop
Niveau 1
Niveau 1
Messages : 12
Enregistré le : mar. 29 nov. 2011 08:17
Status : Hors ligne

Re: [..] Runas en mode console

#5

Message par highsnoop »

Merci de ce retour

J'ai déjà lu la doc sur le runas et je n'ai pas de problème pour afficher la sortie sur la console père (voir script)

Avec le runas je ne peux pas récupérer le code sortie de la commande et donc de ce fait je ne peux pas faire un exit avec l' exitcode de la commande
opt_flag [optional] Controls various options related to how the parent and child process interact.
0x1 ($STDIN_CHILD) = Provide a handle to the child's STDIN stream
0x2 ($STDOUT_CHILD) = Provide a handle to the child's STDOUT stream
0x4 ($STDERR_CHILD) = Provide a handle to the child's STDERR stream
0x8 ($STDERR_MERGED) = Provides the same handle for STDOUT and STDERR. Implies both $STDOUT_CHILD and $STDERR_CHILD.
0x10 ($STDIO_INHERIT_PARENT) = Provide the child with the parent's STDIO streams. This flag can not be combined with any other STDIO flag. This flag is only useful when the parent is compiled as a Console application.
0x10000 ($RUN_CREATE_NEW_CONSOLE) = The child console process should be created with it's own window instead of using the parent's window. This flag is only useful when the parent is compiled as a Console application.



Return Value
Success: The PID of the process that was launched.
Failure: Returns 0 and sets @error to non-zero.
Je cherche aussi du coté de LogonUser et CreateProcessAsUser
Avatar du membre
sylvanie
Niveau 11
Niveau 11
Messages : 1556
Enregistré le : jeu. 26 juil. 2007 21:31
Localisation : Paris
Status : Hors ligne

Re: [..] Runas en mode console

#6

Message par sylvanie »

Bonjour
Et si au lieu de lancer votre executable directement via runas, vous faisiez un .bat du type :

Code : Tout sélectionner

@ECHO OFF
notepad.exe
echo %ERRORLEVEL%
 
où notepad.exe ici joue le rôle de votre binaire. Ceci produira comme dernière sortie le code retours. Quitte à le rediriger vers un fichier pour l'exploiter par la suite
Toi qui cherche à mettre le doigt sur la solution, appuie sur F1.
highsnoop
Niveau 1
Niveau 1
Messages : 12
Enregistré le : mar. 29 nov. 2011 08:17
Status : Hors ligne

Re: [..] Runas en mode console

#7

Message par highsnoop »

Je ne peux pas lancer directement ma commande via un bat car je doit "l'executer en tant que".

Sinon cela aurait été trop simple. :P

Sinon est-il tout simplement possible de récupérer le code sortie de la runas ? en utilisant les API OpenProcess et GetExitCodeProcess.
Avatar du membre
sylvanie
Niveau 11
Niveau 11
Messages : 1556
Enregistré le : jeu. 26 juil. 2007 21:31
Localisation : Paris
Status : Hors ligne

Re: [..] Runas en mode console

#8

Message par sylvanie »

Et alors ?
C'est le .bat que vous lancez via Runas.
Toi qui cherche à mettre le doigt sur la solution, appuie sur F1.
highsnoop
Niveau 1
Niveau 1
Messages : 12
Enregistré le : mar. 29 nov. 2011 08:17
Status : Hors ligne

Re: [..] Runas en mode console

#9

Message par highsnoop »

je ne comprend pas !!

shell1
|
-->runas cmd1
|
->cmd1

je voudrais que le code sortie de runas soit egal au code sortie de cmd1 (voir commande runaswait) mais en affichant le stdout+stderr sur le shell1
Avatar du membre
sylvanie
Niveau 11
Niveau 11
Messages : 1556
Enregistré le : jeu. 26 juil. 2007 21:31
Localisation : Paris
Status : Hors ligne

Re: [..] Runas en mode console

#10

Message par sylvanie »

procédons par étape :

compiler ce script en mode non GUI :
► Afficher le texte
mettre l'exe à un endroit fixe joignable par le user pour lequel on utilisera Runas (j'ai pris C:\ par lâcheté) et je le nomme totrash.exe

Créons maintenant le .bat suivant (toujours sous C:\ ) que nous nommerons exittest.bat
► Afficher le texte
Maintenant créons le script lanceur (celui qui concerne donc le post ) :
► Afficher le texte
Le dernier élément retourné est bien le Exit 8 et l'exe est bien lancer en tant que userautre
Toi qui cherche à mettre le doigt sur la solution, appuie sur F1.
highsnoop
Niveau 1
Niveau 1
Messages : 12
Enregistré le : mar. 29 nov. 2011 08:17
Status : Hors ligne

Re: [..] Runas en mode console

#11

Message par highsnoop »

et quel est le résultat de "echo %ERRORLEVEL%" après le script lanceur

il est égal à 0 et non à 8

Je ne veux pas afficher le code de sortie mais que le lanceur fasse un exit du code sortie de la commande passe en runas
Avatar du membre
sylvanie
Niveau 11
Niveau 11
Messages : 1556
Enregistré le : jeu. 26 juil. 2007 21:31
Localisation : Paris
Status : Hors ligne

Re: [..] Runas en mode console

#12

Message par sylvanie »

et bien on redirige vers une sortie fichier et on exploite ...

le . bat devient :

Code : Tout sélectionner

@ECHO OFF
del C:\TEMP\reultat.log
C:\totrash.exe
echo %ERRORLEVEL% > C:\TEMP\reultat.log
 
et le lanceur :
► Afficher le texte
Toi qui cherche à mettre le doigt sur la solution, appuie sur F1.
highsnoop
Niveau 1
Niveau 1
Messages : 12
Enregistré le : mar. 29 nov. 2011 08:17
Status : Hors ligne

Re: [..] Runas en mode console

#13

Message par highsnoop »

j'ai pensé a cette solution mais c'est du quick and dirty

De plus je ne suis pas sur à 100% que le compte utilisé dans le runas ai le droit d’écrire dans un répertoire commun. (je dépend des policies AD) sans compter que ce code tournera sur plusieurs system donc pas forcement la même arborescence.
Et si j'utilise une variable system je ne suis pas sur d'avoir la même valeur que celle du shell père.

J'essaye de récupérer le code sortie sans passer par un fichier.

j'ai trouvé du code avec GetExitCodeProcess mais je n'arrive pas à récupérer le code de sortie.
Avant la mise en place de RUNAS et RUNASWAIT je pense que l'on pouvait écrire du code "en tant que" donc de placer le code sortie dans une variable mais je n'ai pas testé.

Je sais je suis compliqué :twisted:
Avatar du membre
sylvanie
Niveau 11
Niveau 11
Messages : 1556
Enregistré le : jeu. 26 juil. 2007 21:31
Localisation : Paris
Status : Hors ligne

Re: [..] Runas en mode console

#14

Message par sylvanie »

Et bien on peut revenir en mode full stdout en triant sur la sortie pour savoir si on affiche dans l'applicatif ou si on traite le retours comme valeur de sortie.
On prend comme patern "Sortie_Exec " sur laquelle on bascule en mode 'réception du code retours' (libre à vous de changer cette patern, le tout est d'éviter les collisions possibles avec la sortie de l’exécutable


le .bat :

Code : Tout sélectionner

@ECHO OFF
C:\totrash.exe
echo Sortie_Exec %ERRORLEVEL%

 
Pour le lanceur :

Code : Tout sélectionner

#include <Constants.au3>

$pid=RunAs("autreuser",@computername,"motdepasse",0,"C:\exittest.bat","C:\",1,$STDOUT_CHILD+$STDERR_CHILD)
$stringout=""
While 1
    $line = StdoutRead($pid)
    If @error Then ExitLoop
    If $line<> "" Then
        if Not StringInStr($line,"Sortie_Exec")  Then
            ConsoleWrite($line)
        Else
            $stringout=StringReplace($line,"Sortie_Exec ","")
        EndIf
    EndIf
Wend
ConsoleWrite("sortie="&$stringout)
Exit $stringout
 
Toi qui cherche à mettre le doigt sur la solution, appuie sur F1.
highsnoop
Niveau 1
Niveau 1
Messages : 12
Enregistré le : mar. 29 nov. 2011 08:17
Status : Hors ligne

Re: [..] Runas en mode console

#15

Message par highsnoop »

Je suis d'accord avec toi c'est une manière déjà plus propre.

Déjà je te remercie de t'être penché sur le problème.

Je vais tester un script en C#, pour voir si je peux éviter de passer par un fichier .bat.

Parce que même si je créé le fichier .bat, qui contient la commande passé en argument, je retourne dans le problème d'écrire un fichier (Voir dans post plus haut - policies;acl;variable...)

Je fais du script depuis plusieurs années (windows et unix) et je sais que ça fonctionnera sur une grande partie du parc mais pas à 100%.

Je préfère perdre un peu de temps avant la mise en place et être sur de ne plus revenir dessus (sauf en cas de nouveau system $crosoft)

Je reste à l'écoute du post si quelqu'un à la solution (sans passer par un fichier annexe).

Et merci à AutoIt qui permet de faire des applications en mode console.
Windows n'est pas qu'un bureau graphique :mrgreen:
Avatar du membre
jchd
AutoIt MVPs (MVP)
AutoIt MVPs (MVP)
Messages : 2284
Enregistré le : lun. 30 mars 2009 22:57
Localisation : Sud-Ouest de la France (43.622788,-1.260864)
Status : Hors ligne

Re: [..] Runas en mode console

#16

Message par jchd »

Très sincèrement, je n'ai pas vraiment creusé cette voie, mais ne serait-il pas possible de se passer totalement du .BAT en créant une NamedPipe dans le lanceur et en y redirigeant la sortie du process lancé ? Un (trop) rapide test montre que ça fonctionne, sauf problèmes de droits.

Maintenant si on se débrouille bien côté droits ça doit pouvoir marcher d'autant plus qu'on s'abtrait de l'arborescence fichiers ... sauf si je me gourre de 100% ce qui est fort possible.
La cryptographie d'aujourd'hui c'est le taquin plus l'électricité.
highsnoop
Niveau 1
Niveau 1
Messages : 12
Enregistré le : mar. 29 nov. 2011 08:17
Status : Hors ligne

Re: [..] Runas en mode console

#17

Message par highsnoop »

En fait je n'arrive pas à récupérer le handle de runas, si je le récupère je pourrais utiliser API GetExitCodeProcess.

Mais j'ai toujours un "acces denied"
► Afficher le texte
Et si ce n'est pas possible en fait je voulais utiliser l' API CreateProcessWithLogonW.

Mes tests en c# ne sont pas concluants car je dépend du framework installé sur les machines :x
highsnoop
Niveau 1
Niveau 1
Messages : 12
Enregistré le : mar. 29 nov. 2011 08:17
Status : Hors ligne

Re: [..] Runas en mode console

#18

Message par highsnoop »

Voici le dernier script

Le problème reste à récupérer la sortie stdout+stderr

Voir la ligne ; erreur retourne = 109:Le canal de communication a été fermé. (vers le bas)
► Afficher le texte
Avatar du membre
jchd
AutoIt MVPs (MVP)
AutoIt MVPs (MVP)
Messages : 2284
Enregistré le : lun. 30 mars 2009 22:57
Localisation : Sud-Ouest de la France (43.622788,-1.260864)
Status : Hors ligne

Re: [..] Runas en mode console

#19

Message par jchd »

Je n'ai actuellement pas trop la possibilité de tracer tout ça. En tout cas, je crois que le bon moyen serait de déjà faire fonctionner les tuyaux indépendemment de la question des droits.

Une chose me semble louche : pourquoi déclares-tu le buffer en wchar ? Tout ce qu'une console peut émettre dans un flux std est soit de l'ANSI (page de code selon réglages en vigueur) soit de l'UTF-8 si tu as un "chcp 65001" dans le démarrage de cmd. En aucun cas (à ma connaissance) on ne peut avoir un flux UTF-16.

Pour moi --et encore une fois, je me plante souvent-- ton flux doit être en char tous bêtes, que ce soit de l'ANSI ou du UTF-8, chaque partie du tuyau devant évidemment respecter la même convention.

Maintenant pour ce qui est du canal fermé, j'essaierai d'y jeter un zieu asap.
La cryptographie d'aujourd'hui c'est le taquin plus l'électricité.
highsnoop
Niveau 1
Niveau 1
Messages : 12
Enregistré le : mar. 29 nov. 2011 08:17
Status : Hors ligne

Re: [..] Runas en mode console

#20

Message par highsnoop »

Je ne pense pas car si tu remplaces

Code : Tout sélectionner

$arrRet = DllCall("advapi32.dll","long","CreateProcessWithLogonW", _
"wstr",$sUserName, _
"wstr","", _
"wstr",$sPassword, _
"dword",$LOGON_WITH_PROFILE, _
"wstr","", _
"wstr",$sCmd, _
"dword",$CREATE_DEFAULT_ERROR_MODE, _
"ptr",0, _
"ptr",0, _
"ptr",$ptrSI, _
"ptr",$ptrPI)
if $arrRet[0]=0 then
Msg("Error in Dllcall " & _WinAPI_GetLastErrorMessage())
Exit
EndIf

If Not @error and $arrRet[0]<>0 Then
par

Code : Tout sélectionner

if not _WinAPI_CreateProcess("", @comspec & " /c ipconfig", 0, 0, True, 0, 0, "",$ptrSI, $ptrPI) then
sans oublier de commenter la ligne pour le msg d'erreur

Code : Tout sélectionner

;Msg("Return of 'CreateProcessWithLogonW' : "& $arrRet[0])
Et bien surprise cela fonctionne.
Je me demande si il n'y pas une coquille sur l'API CreateProcessWithLogonW avec la récupération stdout.

Je vais tester avec les fonctions logonuser et createprocessasuser voir si j'ai le même résultat
Répondre