3 / 0 / 0
Регистрация: 17.05.2012
Сообщений: 10
1

Создание процесса cmd и передача команд - TASM, WinAPI

12.09.2012, 11:02. Показов 4917. Ответов 11
Метки нет (Все метки)

Здравствуйте, форумчане!

Нужна помощь в реализации обработки команд DOS-интерпретатора под win32. Сам cmd.exe не должен создавать окно, а команды получать, например, из текстового файла, ну или для простоты пока в виде строки из запустившей его программы на асме. Такое сделать реально? Вот мой нерабочий исходник на основе примеров из учебника Пирогова:

Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
    .386                                
.model  flat,stdcall
;include WindowA.inc
    extrn GetModuleHandleA:PROC
    extrn ExitProcess:PROC
    extrn GetStdHandle:PROC
    extrn WriteConsoleA:PROC
    extrn CreateProcessA:PROC
    extrn CloseHandle:PROC
    extrn CreatePipe:PROC
 
STD_INPUT_HANDLE equ -11
SW_HIDE equ 0
STARTF_USESHOWWINDOW equ 1h
STARTF_USESTDHANDLES equ 100h
STARTF_ADD = STARTF_USESHOWWINDOW + STARTF_USESTDHANDLES
    
STARTUP STRUC
     cb                dd 0
     lpReserved        dd 0
     lpDesktop         dd 0
     lpTitle           dd 0
     dwX               dd 0
     dwY               dd 0
     dwXSize           dd 0
     dwYSize           dd 0
     dwXCountChars     dd 0
     dwYCountChars     dd 0
     dwFillAttribute   dd 0
     dwFlags           dd 0
     wShowWindow       dw 0
     cbReserved2       dw 0
     lpReserved2       dd 0
     hStdInput         dd 0
     hStdOutput        dd 0
     hStdError         dd 0
STARTUP ENDS
 
PROCINF STRUC
    hProcess dd ?
    hThread  dd ?
    Idproc   dd ?
    idThr    dd ?
PROCINF ENDS
 
.data    
    hInst dd 0
    Path db "c:\windows\system32\cmd.exe",0
    RES dd ?
    String db "del c:\1.txt"
    Slen equ $-String
    HW dd ?
    HR dd ?
    HTHR dd ?
    STRUP STARTUP <?>
    INF PROCINF <?>
    
.code
 
start:
    call GetModuleHandleA,0
    mov hInst,eax
    call CreatePipe,offset HR,offset HW,0,0
    mov eax,HW
    mov STRUP.cb,68
    mov STRUP.lpReserved,0
    mov STRUP.lpDesktop,0
    mov STRUP.lpTitle,0
    mov STRUP.dwFlags,STARTF_ADD
    mov STRUP.cbReserved2,0
    mov STRUP.lpReserved2,0
    mov STRUP.wShowWindow,SW_HIDE
    mov STRUP.hStdInput,eax
;   mov STRUP.hStdError,eax
    call CreateProcessA,0,offset Path,0,0,1,0,0,0,offset STRUP,offset INF
    call GetStdHandle,STD_INPUT_HANDLE
    call WriteConsoleA,HR,offset String,Slen,offset RES
;link:   jmp link
    call ExitProcess, 0
end     start
Как передать строку String? Через канал? Нужно ли создавать новый поток? Вообще в каком направлении мне двигаться ?
0

Помощь в написании контрольных, курсовых и дипломных работ здесь.

Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
12.09.2012, 11:02
Ответы с готовыми решениями:

Передача команд в cmd
Здравствуйте! Подскажите как можно передавать команды в cmd допустим запустил я ее, потом хочу...

Передача команд в cmd.exe
Добрый вечер, участники форума! Столкнулся с такой проблемой. Существует библиотека MALLET...

Передача входных данных для CMD команд
Добрый день ! Столкнулся с такой бедой в консольном приложении : многие команды cmd дополнительные...

Передача консольных команд в CMD через system("");
Всем привет! Подскажите как выполнять консольные команды через system с правами администратора?...

11
390 / 178 / 2
Регистрация: 14.03.2012
Сообщений: 443
13.09.2012, 06:59 2
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
.386
    .model         flat, stdcall
    option         casemap :none
 
    include        \masm32\include\windows.inc
    include        \masm32\include\kernel32.inc
    includelib     \masm32\lib\kernel32.lib
    
    .code
    
    CmdCommand db 'cmd /c echo hello world! && pause',0
 
start:
 
    invoke WinExec,addr CmdCommand,SW_SHOW  ; юзать SW_HIDE и окно будет скрыто
    invoke ExitProcess,NULL
 
end start
1
3 / 0 / 0
Регистрация: 17.05.2012
Сообщений: 10
13.09.2012, 14:26  [ТС] 3
_lucius_, с masm знаком мало, а нижеприведенный вариант на tasm не прокатил. Винда выдает ошибку записи по адресу, похоже в самом начале. С какими ключами собираешь exe-шники в masm? Вот мой вариант:
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
.386                           
    .model  flat,stdcall
    
    extrn WinExec:proc
    extrn ExitProcess:proc
    
    SW_HIDE equ 0
    SW_SHOW equ 5
    
    .code
    
    CmdCommand db 'cmd /c echo hello world! && pause',0
 
start:
 
    call WinExec,offset CmdCommand,SW_HIDE
    call ExitProcess,0
 
end start
Добавлено через 14 минут
Еще нарыл на Исходниках.ru вот что:
Кликните здесь для просмотра всего текста

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
//------------Пример использования CreateProcess и Anonymous Pipes------
 
// childspawn.cpp
// Приложение запускает shell и перехватывает его ввод/вывод
 
//---------------------use freely---------------------------------------
 
#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <string.h>
#pragma hdrstop
#include <condefs.h>
 
 
 
#define bzero(a) memset(a,0,sizeof(a)) //для сокращения писанины
 
 
 
bool IsWinNT()  //проверка запуска под NT
{
  OSVERSIONINFO osv;
  osv.dwOSVersionInfoSize = sizeof(osv);
  GetVersionEx(&osv);
  return (osv.dwPlatformId == VER_PLATFORM_WIN32_NT);
}
 
 
 
void ErrorMessage(char *str)  //вывод подробной информации об ошибке
{
 
  LPVOID msg;
 
  FormatMessage(
    FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
    NULL,
    GetLastError(),
    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // язык по умолчанию
    (LPTSTR) &msg,
    0,
    NULL
  );
 
  printf("%s: %s\n",str,msg);
  LocalFree(msg);
 
}
 
 
 
//----------------------------------------------------------------------
 
void main()
 
{
 
  char buf[1024];           //буфер ввода/вывода
 
 
 
  STARTUPINFO si;
  SECURITY_ATTRIBUTES sa;
  SECURITY_DESCRIPTOR sd;        //структура security для пайпов
  PROCESS_INFORMATION pi;
 
  HANDLE newstdin,newstdout,read_stdout,write_stdin;  //дескрипторы
                                                      // пайпов
 
 
  if (IsWinNT())        //инициализация security для Windows NT
  {
    InitializeSecurityDescriptor(&sd,SECURITY_DESCRIPTOR_REVISION);
    SetSecurityDescriptorDacl(&sd, true, NULL, false);
    sa.lpSecurityDescriptor = &sd;
  }
 
  else sa.lpSecurityDescriptor = NULL;
 
  sa.nLength = sizeof(SECURITY_ATTRIBUTES);
  sa.bInheritHandle = true;       //разрешаем наследование дескрипторов
 
 
  if (!CreatePipe(&newstdin,&write_stdin,&sa,0))   //создаем пайп
                                                   // для stdin
  {
    ErrorMessage("CreatePipe");
    getch();
    return;
  }
 
  if (!CreatePipe(&read_stdout,&newstdout,&sa,0)) //создаем пайп
                                                  // для stdout
  {
    ErrorMessage("CreatePipe");
    getch();
    CloseHandle(newstdin);
    CloseHandle(write_stdin);
    return;
  }
 
 
 
  GetStartupInfo(&si);      //создаем startupinfo для
                            // дочернего процесса
 
  /*
 
  Параметр dwFlags сообщает функции CreateProcess
  как именно надо создать процесс.
 
  STARTF_USESTDHANDLES управляет полями hStd*.
  STARTF_USESHOWWINDOW управляет полем wShowWindow.
 
  */
 
  si.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;
  si.wShowWindow = SW_HIDE;
  si.hStdOutput = newstdout;
  si.hStdError = newstdout;   //подменяем дескрипторы для
  si.hStdInput = newstdin;    // дочернего процесса
 
  char app_spawn[] = "d:\\winnt\\system32\\cmd.exe"; //это просто
                                                     // пример,
                                                     //замените на то,
                                                     // что вам нужно
 
 
 
  //создаем дочерний процесс
 
  if (!CreateProcess(app_spawn,NULL,NULL,NULL,TRUE,CREATE_NEW_CONSOLE,
                     NULL,NULL,&si,&pi))
  {
    ErrorMessage("CreateProcess");
    getch();
    CloseHandle(newstdin);
    CloseHandle(newstdout);
    CloseHandle(read_stdout);
    CloseHandle(write_stdin);
    return;
  }
 
 
 
  unsigned long exit=0;  //код завершения процесса
  unsigned long bread;   //кол-во прочитанных байт
  unsigned long avail;   //кол-во доступных байт
 
 
 
  bzero(buf);
 
  for(;;)      //основной цикл программы
  {
    GetExitCodeProcess(pi.hProcess,&exit); //пока дочерний процесс
                                           // не закрыт
    if (exit != STILL_ACTIVE)
      break;
 
    PeekNamedPipe(read_stdout,buf,1023,&bread,&avail,NULL);
 
    //Проверяем, есть ли данные для чтения в stdout
 
    if (bread != 0)
    {
      bzero(buf);
      if (avail > 1023)
      {
        while (bread >= 1023)
        {
          ReadFile(read_stdout,buf,1023,&bread,NULL);  //читаем из
                                                       // пайпа stdout
          printf("%s",buf);
          bzero(buf);
        }
      }
 
      else {
        ReadFile(read_stdout,buf,1023,&bread,NULL);
        printf("%s",buf);
      }
    }
 
    if (kbhit())      //проверяем, введено ли что-нибудь с клавиатуры
    {
      bzero(buf);
      *buf = (char)getche();
 
      //printf("%c",*buf);
 
      WriteFile(write_stdin,buf,1,&bread,NULL); //отправляем это
                                                // в stdin
 
      if (*buf == '\r') {
        *buf = '\n';
        printf("%c",*buf);
        WriteFile(write_stdin,buf,1,&bread,NULL); //формирум конец
                                                  //строки, если нужно
 
      }
    }
  }
 
  CloseHandle(pi.hThread);
  CloseHandle(pi.hProcess);
  CloseHandle(newstdin);            //небольшая уборка за собой
  CloseHandle(newstdout);
  CloseHandle(read_stdout);
  CloseHandle(write_stdin);
}
 
//----------------------------EOF-----------------------------------
 
//------------------------------------------------------------------

Опять же создание каналов. Подойдет ли это для моего случая? Если да, то имеет смысл перевести в асм куски сишного кода. Тем более API там те же самые, которые я пробовал брать с самого начала.
0
Клюг
7670 / 3185 / 382
Регистрация: 03.05.2011
Сообщений: 8,381
13.09.2012, 17:01 4
Цитата Сообщение от Ballast
Еще нарыл на Исходниках.ru вот что
Пришлось брать напильник, чтобы откомпилилось. На консоль вообще ничего не выдаёт, ни ошибок, ни версии cmd, которую запросил. Под отладчиком ковырять лень.
0
390 / 178 / 2
Регистрация: 14.03.2012
Сообщений: 443
13.09.2012, 17:16 5
Цитата Сообщение от Ballast Посмотреть сообщение
С какими ключами собираешь exe-шники в masm?
C:\masm32\bin\ml /c /coff %1.asm
C:\masm32\bin\Link /SUBSYSTEM:WINDOWS %1.obj
0
Клюг
7670 / 3185 / 382
Регистрация: 03.05.2011
Сообщений: 8,381
13.09.2012, 17:58 6
Цитата Сообщение от Ballast
вариант на tasm
ВотЪ. Всё-таки бугланд - аццкий аццтой.
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
;tasm32 /ml winexec.asm
;tlink32 winexec.obj,,,D:\WC11\lib386\nt\kernel32.lib - путь до либы сменить!
;или wlink form win nt fi winexec lib kernel32.lib
    .386
    .model  flat,stdcall
    SW_HIDE = 0
    SW_SHOW = 5
 
    extrn   _WinExec@8:PROC
    extrn   _ExitProcess@4:PROC
    .data
    CmdCommand  db 'cmd /c echo hello world! && pause',0
 
    .code
start:
 
    call    _WinExec@8, offset CmdCommand, SW_SHOW; юзать SW_HIDE и окно будет скрыто
    call    _ExitProcess@4, 0
 
    end start
0
3 / 0 / 0
Регистрация: 17.05.2012
Сообщений: 10
13.09.2012, 23:29  [ТС] 7
Цитата Сообщение от Charles Kludge Посмотреть сообщение
бугланд - аццкий аццтой
Пожалуй, согласен. Надо в макроасм углубляться.
Вариант _lucius_а запустился, а тасмовый не прожевал либу kernel32 из того же масма, т.к. собственной такой же в нем не нашлось Про wlink впервые слышу, откуда это?
0
Клюг
7670 / 3185 / 382
Регистрация: 03.05.2011
Сообщений: 8,381
13.09.2012, 23:47 8
Цитата Сообщение от Ballast
Про wlink впервые слышу, откуда это?
Из OpenWatcom C, есть форк JWLINK, равно как и JWASM - сайт вообще интересный.
0
Ушел с форума
Автор FAQ
14256 / 7125 / 854
Регистрация: 11.11.2010
Сообщений: 12,772
14.09.2012, 04:23 9
Ballast, для tasm код _lucius_ выглядит вот так
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
.386                           
    .model  flat,stdcall
    includelib import32.lib
    
    extrn WinExec:proc
    extrn ExitProcess:proc
    
    SW_HIDE equ 0
    SW_SHOW equ 5
    
    .code
    
    CmdCommand db 'cmd /c echo hello world! && pause',0
 
start: push SW_HIDE
    push offset CmdCommand
    call WinExec
    push 0
    call ExitProcess 
end start
bat-файл для сборки выглядит так
Код
cls ;стираю всё с экрана
set tasm_path= путь к директории где находятся tasm32 и tlink32
set filename= имя твоего файла без расширения asm
%tasm_path%\bin\tasm32 /I%tasm_path%\include\TASM /q /z %filename%.asm  %filename%.obj /ml/m3
%tasm_path%\bin\ilink32 -L%tasm_path%\lib /Tpe /aa /c /o /x %filename%.obj
if exist %filename%.map del %filename%.map ;удаляю мусор
if exist %filename%.obj del %filename%.obj
if exist %filename%.ilc del %filename%.ilc
if exist %filename%.ild del %filename%.ild
if exist %filename%.ilf del %filename%.ilf
if exist %filename%.ils del %filename%.ils
if exist %filename%.tds del %filename%.tds
файл import32.lib я выкладывал здесь
1
Клюг
7670 / 3185 / 382
Регистрация: 03.05.2011
Сообщений: 8,381
14.09.2012, 08:34 10
Цитата Сообщение от Mikl___
set filename= имя твоего файла без расширения asm
А так? d и p - just for your taste.
Код
set filename=%~dpn1
1
Ушел с форума
Автор FAQ
14256 / 7125 / 854
Регистрация: 11.11.2010
Сообщений: 12,772
14.09.2012, 11:09 11
Charles Kludge, это уже будет шаг к универсальному батнику
0
3 / 0 / 0
Регистрация: 17.05.2012
Сообщений: 10
14.09.2012, 13:56  [ТС] 12
Вроде разобрался с обоими. Спасибо всем!
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
14.09.2012, 13:56

tasm и winapi
Возможно ли связать ассемблер и win api? Необходимо устроить отключение мыши на компьютере!

Получение команд из CMD
Собственно, есть тривиальная задача написания программы на С++ с CLI(не путать с C++/CLI...

Выполнение команд в cmd
Здравствуйте форумчане! Пробую написать программу для смены ip путем ввода 2х команд в cmd,нашел...

Несколько команд в cmd
Мне нужно через консоль c# запустить cmd и выполнить в нем несколько команд. Сколько я не искал в...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
12
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.