Что нового

exe компилятор на AutoIt

Microteam

Осваивающий
Сообщения
74
Репутация
34
Всем привет! Всех с рождеством! :smile: Итак, мы сейчас с Вами напишем exe компилятор на autoit для выдуманного на ходу командного языка программирования Au3Comm. Описывать, я свой "язык программирования" тут не буду. Если Вам интересно, статью можете почитать тут: клац!

А мы с Вами начнём написание exe компилятора. Итак, мы конечно же можем, транслировать команды в машинный код, это будет будет работать быстрее самого AutoIt'a. Но, мы с Вами создадим свою среду времени Выполнения, а.к.а Runtime. Как это будет работать?

1. Мы создаем ядро runtime на autoit;
2. Читаем данные по сигнатуре(уникальной подписи, которую мы придумаем);
3. Выполняем.

Итак вот код нашего рантайма:
Код:
#cs
   Исходник времени выполнения Au3Comm
   Au3Comm Runtime
#ce

Global $FilePath = @ScriptFullPath; в этой глобальной переменной будет храниться путь до выполняемого скрипта
Global $FileDir = @ScriptDir; в это переменной будет храниться папка из которой запущен скрипт

; Подключаем движок интерпретатора
#include "..\lib\engine.au3"

; Подключаем список команд и их обработчики
#include "..\lib\commands.au3"

; Подключаем сигнатуру нашего скрипта
#include "..\lib\signature.au3"

If Not @Compiled Then Exit

$script = FileRead(@ScriptFullPath) ; Читаем текущий файл

$sign_pos = StringInStr($script, $Signature) ; Узнаем позицию сигнатуры в нашем файле

; Если сигнатура не найдена, то начинаем быковать
If $sign_pos = 0 Then
   MsgBox(16, "Au3Comm Runtime error", "Сигнатура не найдена");
   Exit
EndIf

$source_pos = $sign_pos + $Signature_size ; узнаем с какого места начинается наш код.


; Если размер исполняемого файла больше чем позиция сигнатуры, быкуем. Потому-что быть такого не может
If $source_pos > FileGetSize(@ScriptFullPath) Then
   MsgBox(16, "Au3Comm Runtime error", "Ошибка чтения кода")
   Exit
EndIf


$script_source = StringMid($script, $source_pos) ; Читаем наш скрипт


ParseCode($script_source, $Commands); Выполняем его
Как видите программа читает сама себя и ищет там сигнатуру(подпись), если сигнатура найдена, то считывает все данные после сигнатуры и исполняет. Для солидности: после компиляции меняем расширение с exe на bin.

А вот исходник компилятора:
Код:
#NoTrayIcon

#include<File.au3>

; Подключаем файл с сигнатурой
#include "lib\signature.au3"


If Not FileExists(@ScriptDir&"\runtime\a3cruntime.bin") Then
   MsgBox(48, "Ошибка компиляции", "Не могу найти файл a3cruntime.bin")
   Exit
EndIf

$Runtime = FileRead(@ScriptDir&"\runtime\a3cruntime.bin"); Читаем наш рантайм

Global $ScriptFile = FileOpenDialog("Au3Comm скрипт", @ScriptDir, "Скрипт Au3Comm (*.a3c)|Все файлы (*.*)")

If Not $ScriptFile Then Exit

$ScriptSource = FileRead($ScriptFile); ЧИтаем наш скрипт

Local $szDrive, $szDir, $szFName, $szExt
_PathSplit($ScriptFile, $szDrive, $szDir, $szFName, $szExt)

$OutFile_Name = $szFName&'.exe'; Формируем название exeшника из названия файла a3c
$OutFile_Path = $szDrive&$szDir&$OutFile_Name; Формируем путь сохранения файла

$OutFile_Out = $Runtime & $Signature & $ScriptSource ; Собираем наш exe файл склеивая рантайм сигнатуру и сам скрипт

FileWrite($OutFile_Path, $OutFile_Out) ; Записываем наш exe файл

If @error = 0 Then
   MsgBox(64, "Au3Comm Compiller", 'Файл "'&$szFName&$szExt&'" успешно скомпилирован!');
Else
   MsgBox(48, "Au3Comm Compiller" , "Ошибка компиляции файла!")
EndIf
Здесь алгоритм тоже очень прост, мы читаем файл a3cruntime.bin (скомпилированный код выше) и склеиваем с сигнатурой и самим исходником a3c скрипта. и сохраняем в exe файл. Вот и наша компиляция.

Теперь, если мы откроем наш скомпилированный a3c скрипт, то увидим, что наши сигнатура и исходник скрипта находятся в конце. Как видите, исходник наш видно и его можно без труда прочитать. Для исправления этого, используют так называемую "обфускацию". Сам исходник, в принципе шифруют и вставляют. А в рантайме пишут функцию, которая расшифровывает скрипт и исполняет, или же можно зашифровать файл алгоритмом RC4 и при запуске запрашивать пароль.

Сам язык Au3Comm конечно не круче самого AutoIt'a, но могу сказать, что он круче языка HQ9+ ;D

Вы можете скачать исходники тут: http://yadi.sk/d/F_HQjPpCFckHt
В примере присутствуют компилятор и интерпретатор.
 

Garrett

Модератор
Локальный модератор
Сообщения
3,999
Репутация
967
Re: Пишем exe компилятор на AutoIt

Предупреждение За нарушение правил форума (пункт Б.5):
Имя темы должно нести смысловую нагрузку (отражать суть вопроса/проблемы)
Правильно сформулированное название темы привлекает больше внимания, и шансы получить конкретный ответ увеличиваются.


Данные правила могут пополняться локальными правилами раздела.
Как правильно называть темы

"Пишем exe компилятор на AutoIt" - это неприемлемое название темы, переименуйте тему иначе она будет закрыта, а вам возможно будет выдан бан на несколько дней.

С уважением, ваш Модератор.










Предупреждение За нарушение правил обязательного оформления публикаций.
Правила обязательного оформления публикаций

Тема "Пишем exe компилятор на AutoIt" должна быть оформлена согласно правилам обязательного оформления публикаций, иначе она будет закрыта.

С уважением, ваш Модератор.
 
Автор
Microteam

Microteam

Осваивающий
Сообщения
74
Репутация
34
Ох, сорри. Дело было ночью. Перепутал. Можно будет переместить тему в полезняшки?
 

joiner

Модератор
Локальный модератор
Сообщения
3,556
Репутация
628
честно сказать, ничего не понял. что и для чего. может от того, что "дело было ночью"? :smile:
Автор, а можно все объяснить попроще. чем это лучше обычной компиляции?
я лишь вижу дополнительные сложности
 

Belfigor

Модератор
Локальный модератор
Сообщения
3,608
Репутация
941
Тем что если ты напишешь свою шифровку, врагу будет сложнее декомпильнуть твой скрипт :smile:
 
Автор
Microteam

Microteam

Осваивающий
Сообщения
74
Репутация
34
joiner, объясню с радостью :smile:

Ну алгоритм компилятора тут очень прост. Сначала мы создаем такую программу, которая открывает (через FileRead) сама себя и ищет там строку !AU3COMMCODE (к примеру) - эта строка называется сигнатура. После этой строки у нас располагается скрипт, который будет исполнен. Эта программа по-солидному называется средой времени выполнения (Runtime Environment). Получается: интерпретатор + сигнатура + исходник скрипта = скомпилированная программа.

Можете открыть скомпилированный скрипт и в конце файла увидеть сигнатуру, а за ней исходник скрипта au3comm.

Компилятор же, берёт Runtime (программу), склеивает с сигнатурой и самим исходником и записывает в файл exe. У нас получается скомпилированная программа. Схожим образом работает сам компилятор AutoIt и (если не заблуждаюсь) программы на .NET Framework, а также SFX-архивы. Щас я могу точно сказать, что на AutoIt можно написать SFX-модуль. (святые угодники, кажется у меня появилась ещё одна идея)

Но, компилятор, который я выложил, не обфусцирует код, это понятно тем, что можно исходник прочитать в конце скомпилированного exe файла.

Мы также можем, исходник компилировать в байт-код и написать runtime для исполнения такового, код уже будет труден для восприятия. В добавление, мы можем зашифровать исходник, а потом просить пароль, или же сжать утилитой UPX (как это делает Jon для компилятора AutoIt).

Перед нами открывается спектр возможностей, главное до всего этого додуматься :smile:
 

Suppir

Продвинутый
Сообщения
967
Репутация
62
Что это дает? Можете пояснить?
 

joiner

Модератор
Локальный модератор
Сообщения
3,556
Репутация
628
Maalik
компилирую скрипт твоей программой, но при запуске получаю


ты все-таки не дал инструкцию как пользоваться
 
Автор
Microteam

Microteam

Осваивающий
Сообщения
74
Репутация
34
Как не дал? Сверху же ссылка?
 

joiner

Модератор
Локальный модератор
Сообщения
3,556
Репутация
628
Maalik
так что по поводу ошибки? скрин выше
 
Автор
Microteam

Microteam

Осваивающий
Сообщения
74
Репутация
34
Он AutoIt код компилиорвать не будет, это компилятор другого типа языка. Например попробуйте ввести в файл:
Код:
sayhelloworld
Или же:
Код:
say@Ваше сообщение
В таком случае код скомпилируется.
 

joiner

Модератор
Локальный модератор
Сообщения
3,556
Репутация
628
значит компилятор написан на AutoIT, но не для AutoIT. тогда смысл темы не понятен.если компилятор для твоего "языка", то причем тут "полезняшки"?
 

Garrett

Модератор
Локальный модератор
Сообщения
3,999
Репутация
967
joiner
Я так понял, Maalik написал для своего "ЯП" компилятор (а правильнее интерпретатор) на ЯП Autoit.
P.S. Честно говоря, большого смысла в этом всём я не вижу.
 

firex

AutoIT Гуру
Сообщения
943
Репутация
208
Интерпретация языка на интерпретируемом языке. :rofl:
Maalik
Сделай тогда уж нормальный разбор выражений, вот к примеру вырезка моих старых издевательств над языком:

Код:
$sampleVar:= ( 50 * 50 ) - Abs( -10 ) //variable assignment
$sampleVar:+ 50 //variable assignment
MsgBox( 64, "Title", "Text" ) //default execute
//internally API - кажется так и не закончил

Код:
Func _FxConsole_CommandEngine( $sCommand )
	Local $_poArray, $_poValue = '', $_poDefault = ''
	Local $_pExec = '^[^\\]'
	Local $_pAssign = '^\$([\w]+)\:([\=\+\-\*\&])(.+)$'
	Local $_pAPIcmd = '(?<=\\|\(|,)([^\(\)\,]+?)(?=\h|\,|\))'
	;Value/@Error/@Extended
	Dim $__exec[3] = [Default, 0, 0]
	Do
		; == variable assignment
		$_poArray = StringRegExp( $sCommand, $_pAssign, 3 )
		If UBound( $_poArray ) = 3 Then
			$_poValue = Execute($_poArray[2])
			$_poDefault = Eval( $_poArray[0] )
			Switch $_poArray[1]
				Case '='
					$_poValue = $_poValue
				Case '+'
					$_poValue += $_poValue
				Case '*'
					$_poValue *= $_poValue
				Case '&'
					$_poValue &= $_poValue
			EndSwitch
			$__exec[1] = Assign( $_poArray[0], $_poValue, 2 )
			If Not $__exec[1] Then _
				Dim $__exec[3] = [$_FXE_BADVAR, 1, 0] ;Bad var

			ExitLoop ;Can only one error /1
		EndIf
		; == default execute
		$_poArray = StringRegExp( $sCommand, $_pExec, 3 )
		If UBound( $_poArray ) = 1 Then
			$_poValue = Execute( $sCommand )
			If $_poValue = '' Then
				Dim $__exec[3] = ['', @Error, @Extended]
				If @Error Then _
					$__exec[0] = $_FXE_BADSYNTAX
			EndIf
			ExitLoop
		EndIf
		; == internally API ;NOT Remove slash!
		If StringLeft( $sCommand, 1 ) = '\' Then ;Address to API
			$_poArray = StringRegExp( $sCommand, $_pAPIcmd, 3 )
			If IsArray( $_poArray ) Then ;And UBound( $_poArray ) > 1
				$_poValue = $_poArray
				_ArrayDisplay( $_poValue )
				ExitLoop
			EndIf
		EndIf
	Until True

	; ===
	If $__exec[0] = Default Then _
		Dim $__exec[3] = [$_poValue, 0, 0]
	If IsArray($__exec[0]) Then _
		$__exec[0] = '*Array[' & UBound( $__exec[0] ) & ']'
	If $__exec[0] = 1 Then _
		$__exec[0] = 'Succeed! (or 1)'

	;Report to the console
	_FxConsole_WCmd( 'Executing', $sCommand )
	If $__exec[1] Then
		_FxConsole_WError( 'FXE', $__exec[0] )
	Else
		_FxConsole_WCmd( 'ReturnEx[' & $__exec[2] & ']', $__exec[0] )
		_Cout( '...' & @LF, $FOREGROUND_GREEN )
	EndIf
EndFunc
 
Верх