Что нового

Скрипт крашится при вызове CallWindowProc

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Раньше у меня вот это работало:

Код:
ConsoleWrite(_Base64Decode('test') & @LF)

Func _Base64Decode($Data)
	Local $Opcode = "0xC81000005356578365F800E8500000003EFFFFFF3F3435363738393A3B3C3DFFFFFF00FFFFFF000102030405060708090A0B0C0D0E0F10111213141516171819FFFFFFFFFFFF1A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132338F45F08B7D0C8B5D0831D2E9910000008365FC00837DFC047D548A034384C0750383EA033C3D75094A803B3D75014AB00084C0751A837DFC047D0D8B75FCC64435F400FF45FCEBED6A018F45F8EB1F3C2B72193C7A77150FB6F083EE2B0375F08A068B75FC884435F4FF45FCEBA68D75F4668B06C0E002C0EC0408E08807668B4601C0E004C0EC0208E08847018A4602C0E00624C00A46038847028D7F038D5203837DF8000F8465FFFFFF89D05F5E5BC9C21000"
	
	Local $CodeBuffer = DllStructCreate("byte[" & BinaryLen($Opcode) & "]")
	DllStructSetData($CodeBuffer, 1, $Opcode)

	Local $Ouput = DllStructCreate("byte[" & BinaryLen($Data) & "]")
	Local $Ret = DllCall("user32.dll", "int", "CallWindowProc", "ptr", DllStructGetPtr($CodeBuffer), _
													"str", $Data, _
													"ptr", DllStructGetPtr($Ouput), _
													"int", 0, _
													"int", 0)

	Return BinaryMid(DllStructGetData($Ouput, 1), 1, $Ret[0])
EndFunc


Но с недавних пор любой скрипт использующий API функцию CallWindowProc крашится, вылетает с кодом -1073741819.

У кого то есть идеи почему это происходит, и главное, можно ли подобное исправить, или стоит написать тикет на оф. сайт?
 

Viktor1703

AutoIT Гуру
Сообщения
1,535
Репутация
413
WinXP SP3, скрипт нормально отработал... может дело в Windows?

Копипаст:
Код:
ConsoleWrite(Hex(-1073741819) & @LF)

Как правило, сообщение об ошибке с кодом 0xc0000005 появляется когда вы пытаетесь запустить какое-либо приложение Windows. Программа “падает” и вы никак не можете ее запустить. Так же бывают варианты следующего сообщения на голубом экране, когда падает вся система: Stop: 0x0000008E (0xC0000005, …, …., …….). Параметры в скобках меняются. Наиболее частые причины ошибки 0xC0000005 - ошибки реестра, неисправная память или другие устройства, некорректные драйвера, вирусы и другие вредоносные программы. Другие частые варианты сообщения об ошибке:
‘Error: access violation 0xC0000005’
“An application error has occurred and an application error log is being generated. Exception: access violation (0xC0000005), Address”
‘Exception 0xc0000005 EXCEPTION_ACCESS_VIOLATION at 0x00000000’
‘Ошибка при инициализации приложения (0xc0000005). Для выхода из приложения нажмите кнопку ОК. ‘
Что означает код 0xc0000005 в сообщении об ошибке?

Наличие кода 0xc0000005 в сообщении об ошибке как правило говорит о неправильном обращении к памяти (memory access violation), по разным причинам.
0xc0000005 Шаг 1: Починка реестра

0xc0000005 и другие ошибки Windows часто случаются из-за ошибок в реестре Windows. Ошибки скапливаются в реестре по мере открытия и закрытия приложений, изменения настроек, установки и удаления приложений, особенно если программы удаляются не полностью, не должным образом или более новые устанавливаются поверх старых. Удалить или исправить ошибочные записи можно вручную, что займет много времени. Кроме того, заддая процедура рекомендована только экспертам из-за повышенного риска повреждения реестра и полного выхода из строя операционной системы.

Для исправления ошибок реестра лучше всего использовать специальные программы, которые не только исправляют реестр и устраняют ошибки Windows, но и ускоряют работу компьютера за счет оптимизации системы, что позволяет сэкономить на обновлении компьютера.
0xc0000005 Шаг 2: Вирус

Ваш компьютер может быть заражен вирусом и в таком случае ошибка 0xc0000005 информирует о том, что системой было предотвращено исполнение вредоносного кода, который использует нехарактерное для обычных программ обращение к памяти.

Установите самую свежую версию надежного антивируса и проверьте систему. Внимание: Проверку на вирусы нужно выполнять регулярно, а не только тогда когда появляются сообщения об ошибках!
0xc0000005 Шаг 3: Память

Ошибка 0xc0000005 может быть вызвана сбойным модулем памяти. Если ошибка появилась после установки новой памяти, скорее всего причина именно в этом. Для начала, убедитесь что память совместима с компьютером и что размер памяти не превышает допустимый для данного компьютера. Если все верно, уберите новую память, если ошибка 0xc0000005 исчезнет - проблема была вызвана именно ею. Для уверенности можно протестировать память с помощью программы MemTest86. Если тест покажет наличие ошибок в модуле, его нужно менять.
0xc0000005 Шаг 3: Предотвращение Выполнения Данных

Часто ошибка 0xc0000005 бывает вызвана функцией Windows Предотвращения Выполнения Данных. Эта функция была введена в Windows SP2 и используется в последующих версиях. Предотвращение Выполнения Данных (ПВД) - это набор программных решений для выполнения дополнительных проверок памяти с целью предотвращения исполнения вредоносного кода. В случае с ПВД ошибка 0xc0000005 - типичный пример неверного обращения к памяти. Подобное использование памяти характерно не только для вирусов, но и для обычных программ. Поэтому, если ошибка 0xc0000005 появилась при запуске приложения которому вы доверяете, определите исключение из ПВД для этого приложения.

И еще многое другое.
Ошибка 0xc0000005
 
Автор
CreatoR

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Viktor1703 [?]
Часто ошибка 0xc0000005 бывает вызвана функцией Windows Предотвращения Выполнения Данных
Точно, дело в этом.

Обязательно нужно добавить в справку, если ещё нету (не помню и не проверял). AZJIO ауу... :whistle:...

Теперь вопрос в том, как программно отключить DEP для своего приложения, т.е как занести в белый список свою программу? :scratch:
 

Viktor1703

AutoIT Гуру
Сообщения
1,535
Репутация
413
предлагают через com строку в Windows 7 делается так...

как выключить DEP в виндовс 7 ?

В консоли cmd с поднятием прав выполнить следующее:
Код:
bcdedit.exe /set {current} nx AlwaysOff

Для включение обратно:
Код:
bcdedit.exe /set {current} nx AlwaysOn

Либо WASM.RU, MSDN
 
Автор
CreatoR

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Viktor1703 [?]
предлагают через com строку в Windows 7 делается так.
Я так понял это полное отключение DEP? Т.е не конкретно для процесса?

Вот, тут уже получше, вот так теперь работает:

Код:
DllCall('Kernel32.dll', 'int', 'SetProcessDEPPolicy', 'dword', 0)

ConsoleWrite(_Base64Decode('test') & @LF)

...


Но судя по MSDN оно не сработает если DEPPolicy равняется AlwaysOff или AlwaysOn, т.е полностью отключена/включена.
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Просто тот вызов написан неправильно. Нельзя запускать код из области данных (aka вирус). AutoIt здесь ни при чем.

Код:
ConsoleWrite(_Base64Decode('test') & @LF)

Func _Base64Decode($Data)

	Local $Opcode = Binary('0xC81000005356578365F800E8500000003EFFFFFF3F3435363738393A3B3C3DFFFFFF00FFFFFF000102030405060708090A0B0C0D0E0F10111213141516171819FFFFFFFFFFFF1A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132338F45F08B7D0C8B5D0831D2E9910000008365FC00837DFC047D548A034384C0750383EA033C3D75094A803B3D75014AB00084C0751A837DFC047D0D8B75FCC64435F400FF45FCEBED6A018F45F8EB1F3C2B72193C7A77150FB6F083EE2B0375F08A068B75FC884435F4FF45FCEBA68D75F4668B06C0E002C0EC0408E08807668B4601C0E004C0EC0208E08847018A4602C0E00624C00A46038847028D7F038D5203837DF8000F8465FFFFFF89D05F5E5BC9C21000')
	Local $Ret, $Length, $pMemory, $tOpcode, $tResult, $sResult

	$Length = BinaryLen($Opcode)
	$Ret = DllCall('kernel32.dll', 'ptr', 'VirtualAlloc', 'ptr', 0, 'ulong_ptr', $Length, 'dword', 0x00001000, 'dword', 0x00000040)
	If (@Error) Or (Not $Ret[0]) Then
		; Error
	EndIf
	$pMemory = $Ret[0]
	$tOpcode = DllStructCreate('byte[' & $Length & ']', $Ret[0])
	DllStructSetData($tOpcode, 1, $Opcode)
	$tResult = DllStructCreate('byte[' & BinaryLen($Data) & ']')
	$Ret = DllCall('user32.dll', 'int', 'CallWindowProc', 'ptr', DllStructGetPtr($tOpcode), 'str', $Data, 'ptr', DllStructGetPtr($tResult), 'wparam', 0, 'lparam', 0)
	If (@Error) Or (Not $Ret[0]) Then
		; Error
	EndIf
	$sResult = BinaryMid(DllStructGetData($tResult, 1), 1, $Ret[0])
	$Ret = DllCall('kernel32.dll', 'int', 'VirtualFree', 'ptr', $pMemory, 'ulong_ptr', 0, 'dword', 0x00008000)
	If (@Error) Or (Not $Ret[0]) Then
		; Error
	EndIf
	Return $sResult
EndFunc   ;==>_Base64Decode


Кстати, твоя функция написана только для x86. Попытка запустить на x64 приведет к аварийному завершению.
 
Автор
CreatoR

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Yashied [?]
тот вызов написан неправильно
Это был как пример.
У меня есть ещё несколько скриптов которые используют этот Opcode (например для проверки MD5).
Как я понял требуется выделять виртуальный участок памяти, и использовать его для структур?

Попытка запустить на x64 приведет к аварийному завершению
Насколько я понял это относится к битности самого процесса, а не системы (это то что я понял с MSDN).
Ну у меня скрипты все для x86, т.ч это не проблема :smile:.
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
CreatoR сказал(а):
Как я понял требуется выделять виртуальный участок памяти, и использовать его для структур?

Нужно выделить блок памяти с разрешением на исполнение кода (последний флаг). Если этого не сделать, то DEP пресечет попытки выполнить код из этой области, посчитав его за вирус. Менеджер памяти в AutoIt не позволяет выделять такие блоки памяти.


Добавлено:
Сообщение автоматически объединено:

CreatoR сказал(а):
У меня есть ещё несколько скриптов которые используют этот Opcode (например для проверки MD5).

Этот Opcode есть не что иное, как скомпилированная функция (машинный код). Ты просто запихиваешь его в память и запускаешь на исполнение. Это позволяет значительно повысить скорость вычислений. Вот хороший пример на эту тему. Там вместо DllCall() я использовал ресурсы WinAPIEx.
 
Верх