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

Получение и изменение аргументов командной строки

26.01.2016, 06:20. Показов 2847. Ответов 2
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
MASM
Доброго времени суток! Задача: получить аргументы, например, ARG1=Value 1st ARG2=Value 2nd, и привести их к виду: ARG1="Value 1st" ARG2="Value 2nd". Количество аргументов изначально неизвестно. Потратил уже 3 дня на поиск решения и попытки реализации - все бестолку. Максимум, что удалось - получит аргументы, но только без цикла и всего несколько, используя GetCl... Естественно, аргументы получены некорректно, то есть ARG1=Value 1st - это 2 аргумента.
P.S.: В masm мои познания почти нулевые, но задача поставлена именно для masm.
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
26.01.2016, 06:20
Ответы с готовыми решениями:

Буфер для аргументов командной строки
Добрый вечер. Недавно начал изучать Asm. Возникли следующие вопросы: ...1 Нашел функцию...

Реализация аргументов командной строки
Существуют ли какие-либо стандартные приемы реализации обработки аргументов командной строки К...

Передача аргументов командной строки
Здравствуйте. Подскажите пожалуйста, зачем в этом коде "return 1;"? #include <iostream> #include...

Передача аргументов из командной строки
Создал ярлык и добавил туда параметр: "C:\Users\UserName\Desktop\123.teplo 1". private void...

2
Terminator of naked apes
832 / 139 / 34
Регистрация: 13.02.2015
Сообщений: 328
27.01.2016, 10:00 2
Как бы выразился в этом случае в имманентно присущей ему интеллигентной манере старина Лесли, "CODE OR GTFO" (например ;о)
0
0 / 0 / 0
Регистрация: 26.01.2016
Сообщений: 3
27.01.2016, 12:25  [ТС] 3
Задача решена! (как частная)
Изначально она была немного глобальнее, поэтому выкладываю код полностью с комментариями и описанием полной версии задачи.
Говорю сразу, в masm я полный ноль, поэтому мои комментарии по большей части могут быть ошибочными (комментировал для себя, на всякий случай). Так же, код нерационален, кто предложит более рациональный вариант, тому честь и хвала

Итак, задача: имеется EXE файл, который запускается через VB-скрипт. Необходимо подменить оригинальный файл (переименовать его), то есть, создать прослойку, которая будет получать от скрипта аргументы, запускать оригинальный файл от имени другого пользователя, автоматически вводить пароль этого пользователя и подставлять аргументы.

Отступление. Неудачные попытки. И как пришел к постановке такой задачи:
Изначально пытался реализовать в EXE запуск VB-скрипта, в котором все это описано, но, тут появились проблемы:
1) Если запускать от имени другого пользователя, а не с его привилегиями, пароль автоматически не подставляется средствами командной строки.
2) Если использовать функцию VBS SendKeys для подстановки пароля, то все хорошо, но... Если по умолчанию в системе стоит русская раскладка клавиатуры, подставляются совершенно другие символы.
Менять раскладку по умолчанию и первоначальный скрипт было нельзя. (даже не спрашивайте, просто нельзя и все)
Именно это меня и подтолкнуло к постановке такой задачи и ее решению.

И, наконец-то, сам код, то есть решение задачи:
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
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
.386
 
OPTION casemap: none
 
INCLUDE \masm32\include\masm32rt.inc
INCLUDELIB \masm32\lib\kernel32.lib
INCLUDELIB \masm32\lib\user32.lib
 
;=======================================================================
; Отладочные функции (если понадобятся)
;=======================================================================
;INVOKE MessageBox, NULL, addr Params, chr$("Debug"),MB_OK
;INVOKE ExitProcess, 0 
 
;=======================================================================
; Описываем переменные
;=======================================================================
.data
DelSymbol       equ " " ;Переменная для подсчета пробелов (содержит символ пробела)
FirstFlag       db 1, 0 ;Переменная для определения наличия аргументов
WinName         db "C:\Windows\System32\runas.exe", 0   ;Заголовок окна для получения хэндлера
StartParam      db "/user:PC-NAME\username ", 0  ;Первая часть строки - параметры для RUNAS
RunFile         db """C:\Program Files (x86)\Vendor\ProgramName_.exe ", 0 ;Полный путь для программы, которой необходимо передать параметры
OpenCMD         db "open", 0    ;Действие для процедуры запуска программы
FileName        db "runas.exe", 0 ;Запускаемая программа
 
;========================================================================
; Выделяем память под динамические переменные
;========================================================================
.data?
Params              db 2048 dup(?)  ;Будет содержать полную строку параметров для RUNAS
TheArray            db 2048 dup(?)  ;Будет содержать элементы массива
tmp                 db 2048 dup(?) ;Будет содержать преобразованную строку входных параметров
Args                db 2048 dup (?) ;Будет содержать строку входных параметров
Arg0                db 2048 dup (?) ;Будет содержать полный путь для текущего EXE
 
;========================================================================
; Код
;========================================================================
.code
start:  
;========================================================================
; Парсинг и преобразование получаемых аргументов
; Аргументы получаем от VB-скрипта
; Для аргументов командной строки резать надо не по {="}, а по {=},
; а так же необходимо увеличить добавляемые кавычки с 2х до 3х
;========================================================================
 
INVOKE lstrcat, ADDR Params, ADDR StartParam ;К значению Params дописываем значение переменной StartParam
 
INVOKE GetCommandLine ;Получаем аргументы командной строки в регистр EAX
INVOKE lstrcat, ADDR Args, eax ;Сохраняем аргументы из регистра EAX в переменную Args
INVOKE GetCL, 0, ADDR Arg0 ;Получаем нулевой аргумент командной строки в регистр EAX - Полный путь к EXE-файлу
 
MOV edi, offset TheArray ;Записываем указатель на TheArray в EDI, приемник
INVOKE crt_strtok, ADDR Args, chr$(" ") ;Режем строку из переменной Args по пробелам
STOSD ;Сдвигаем указатель массива TheArray и записываем результат "Резки" из регистра EAX
MOV ebx, eax ;Заносим результат "Резки" из регистра EAX в EBX
.WHILE ebx ;Организуем цикл, пока не опустошим регистр EBX
    INVOKE crt_strtok, NULL, chr$(" ") ;Продолжаем резать строку из переменной Args
    STOSD ;Сдвигаем указатель массива TheArray и записываем результат "Резки" из регистра EAX
    MOV ebx, eax ;Заносим результат "Резки" из регистра EAX в EBX
.ENDW ;Конец цикла
 
XOR ecx, ecx ;Обнуляем регистр ECX
LEA esi, Arg0 ;Получаем указатель на переменную Arg0
Next: ;Метка, если найден
    CMP byte ptr [esi], DelSymbol ;Ищем пробелы в строке из переменной Arg0
    JNZ Notfound ;Переходим на метку, если не найден
    INC ecx ;Иначе, увеличиваем счетчик (значение регистра ECX) на 1
Notfound: ;Метка, если не найден
    INC esi ;Переходим на следующий символ
    CMP byte ptr [esi], 0 ;Проверяем равен ли текущий символ 0
    JZ ExitLoop ;Если равен, значит конец строки, переходим на метку
    JMP Next ;Иначе возвращаемся в начало цикла (переходим на метку)
ExitLoop: ;Метка, если цикл закончен (достигнут конец строки)
    INC ecx ;Увеличиваем значение счетчика (значение регистра ECX) на 1
 
MOV esi, offset TheArray ;Получаем указатель TheArray в ESI, источник
.WHILE ecx ;Организуем цикл, пока значение регистра ECX > 0
    LODSD ;Сдвигаем массив, удаляя элемент вначале (переносим его в EAX)
    DEC ecx ;Уменьшаем значение регистра ECX на 1
.ENDW ;Конец цикла
   
.WHILE 1 ;Организуем бесконечный цикл
    LODSD ;Сдвигаем массив, удаляя элемент вначале (переносим его в EAX)
    .BREAK .IF !eax ;Если достигнут конец массива, выходим из цикла
    PUSH eax ;Прячем значение регистра EAX в стек
    INVOKE InString, 1, eax, chr$("=""") ;Проверяем наличие символов {="}
    .IF sdword ptr eax >= 1 ;Проверяем, найден ли символ
        .IF FirstFlag == 1 ;Проверяем значение переменной FirstFlag
            DEC byte ptr [FirstFlag] ;Если оно эквивалентно 1, меняем значение этой переменной на 0
            INVOKE lstrcat, ADDR tmp, chr$(" ") ;Дописываем к значению переменной tmp символ пробела
        .ELSE ;Иначе (если значение отлично от 1)
            INVOKE lstrcat, ADDR tmp, chr$("""""") ;Дописываем к значению переменной tmp две кавычки
            INVOKE lstrcat, ADDR tmp, chr$(" ") ;Дописываем к значению переменной tmp символ пробела
        .ENDIF ;Конец блока условий
        POP eax ;Восстанавливаем значение регистра EAX из стека
        INVOKE crt_strtok, eax, chr$("=") ;Режем строку из регистра EAX по символам {=} - получаем левую часть
        MOV ebx, eax ;Заносим результат "Резки" из регистра EAX в EBX
        PUSH edx ;Прячем значение регистра EDX в стек (оставшаяся часть строки после резки)
        INVOKE lstrcat, ADDR tmp, eax ;Дописываем к значению переменной tmp значение регистра EAX
        INVOKE lstrcat, ADDR tmp, chr$("=") ;Дописываем к значению переменной tmp символ {=}
        INVOKE lstrcat, ADDR tmp, chr$("""""") ;Дописываем к значению переменной tmp две кавычки
        POP edx ;Восстанавливаем значение регистра EDX из стека
        INVOKE crt_strtok, edx, chr$("=") ;Продолжаем резать строку из регистра EDX - получаем правую часть
        MOV ebx, eax ;Заносим результат "Резки" из регистра EAX в EBX
        INVOKE lstrcat, ADDR tmp, eax ;Дописываем к значению переменной tmp значение регистра EAX
    .ELSE ;Если символ не найден
        INVOKE lstrcat, ADDR tmp, chr$(" ") ;Дописываем к значению переменной tmp символ пробел
        POP eax ;Восстанавливаем значение регистра EAX из стека
        INVOKE lstrcat, ADDR tmp, eax ;Дописываем к значению переменной tmp значение регистра EAX
    .ENDIF ;Конец блока условий
.ENDW ;Конец цикла
 
.IF FirstFlag == 0 ;Проверяем значение переменной FirstFlag, если оно эквивалентно 0, значит командная строка содержит аргументы
    INVOKE lstrcat, ADDR tmp, chr$("""") ;Дописываем к значению переменной tmp одну кавычку
.ENDIF ;Конец блока условий
 
INVOKE lstrcat, addr Params, addr RunFile ;Дописываем к значению Params значение переменной RunFile
INVOKE lstrcat, addr Params, addr tmp ;Дописываем к значению Params значение переменной tmp
INVOKE lstrcat, addr Params, chr$("""") ;Дописываем к значению переменной Params одну кавычку
 
;========================================================================
; Запуск файла от имени другого пользователя
;========================================================================
INVOKE ShellExecute, 0, addr OpenCMD, addr FileName, addr Params, 0, SW_SHOW  ;Запуск cmd.exe и выполнение runas.exe
INVOKE Sleep, 100 ;Пауза 0.1 сек
INVOKE FindWindow, 0, offset WinName ;Поиск нужного окна, для организации ввода
MOV edi, eax ;Сохраняем хэндлер окна для работы
 
INVOKE SendMessage, edi, WM_CHAR, 'p', 0 ;Посимвольный ввод пароля
INVOKE Sleep, 10 ;с интервалом в 0.01 сек
INVOKE SendMessage, edi, WM_CHAR, 'a', 0 ;etc...
INVOKE Sleep, 10
INVOKE SendMessage, edi, WM_CHAR, 's', 0
INVOKE Sleep, 10
INVOKE SendMessage, edi, WM_CHAR, 's', 0
INVOKE Sleep, 10
INVOKE SendMessage, edi, WM_CHAR, 'w', 0
INVOKE Sleep, 10
INVOKE SendMessage, edi, WM_CHAR, 'o', 0
INVOKE Sleep, 10
INVOKE SendMessage, edi, WM_CHAR, 'r', 0
INVOKE Sleep, 10
INVOKE SendMessage, edi, WM_CHAR, 'd', 0
INVOKE Sleep, 10
INVOKE SendMessage, edi, WM_CHAR, 10, 0 ;Посылаем символы перехода на следующую строку aka ENTER - 1310
INVOKE Sleep, 10
INVOKE SendMessage, edi, WM_CHAR, 13, 0
INVOKE Sleep, 10
INVOKE ExitProcess, 0 ;Завершаем работы программы
;========================================================================
END start
Как-то так... Свои функции программа выполняет, а значит задача решена. Возможно, пароль и имя файла, зашитые в программу - это минус, но мне нужен был костыль, и я его получил.
P.S.: Кроме тех, кто возьмется (если такие найдутся) за оптимизацию кода, отдельная благодарность тем, кто подправит мои комментарии

Добавлено через 13 минут
Чуть не забыл, результаты:
На входе: ARG1=VALUE ARG2="Second value" ARG3="Date is 01.01.1970" ARG4="Time is 00:00:00"
На выходе (подставляем в RUNAS):
1) если аргументы заданы: /user:PC-NAME\username "C:\Program Files (x86)\Vendor\ProgramName_.exe ARG1=VALUE ARG2="""Second value""" ARG3="""Date is 01.01.1970""" ARG4="""Time is 00:00:00""""
2) если аргументы не заданы: /user:PC-NAME\username "C:\Program Files (x86)\Vendor\ProgramName_.exe "
0
27.01.2016, 12:25
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
27.01.2016, 12:25
Помогаю со студенческими работами здесь

Разбор аргументов командной строки
#!/usr/bin/python3.4 # -*- coding: UTF-8 -*- import sys import argparse import os...

Вывод аргументов командной строки
Здравствуйте, вот такой пример : package main import ( "fmt" "os" )

Передача аргументов из командной строки
В С можно так: int main(int argc, char* argv) Есть ли какой аналог для паскаля? FPC написан на...

Передача аргументов командной строки
Смысл в том, что бы реализовать switch по количеству аргументов командной строки, выполняя при этом...


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

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

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru