Wichtig ist: Man muss Ahnung haben, um den Scanner etwas (spezielle Sachen) tun zu lassen. Wovon man Ahnung hat, ist egal.
Und mit Profan, das einzige womit ich mich auseinander gesetzt habe, ist bei mir noch lange nicht drin.
Wichtig ist: Man muss Ahnung haben, um den Scanner etwas (spezielle Sachen) tun zu lassen. Wovon man Ahnung hat, ist egal.
Und mit Profan, das einzige womit ich mich auseinander gesetzt habe, ist bei mir noch lange nicht drin.
...schaust du dir aber das Script an, was spricht, ist bereits ohne irgendetwas programmieren zu können wohl offensichtlich, was man genau ändern muss, um andere Sachen sprechen zu lassen. Lesen zu können reicht da eigentlich aus.
Das Tool ist erst mal ein Komprimierer von Möglichkeiten zur Analyse von Rechnern - und zwar nicht nur von Möglichkeiten, die der Programmierer des Tools mitbringt (nirgendwo ist programmiert, das der PPFScanner sprechen kann), sondern von Möglichkeiten ganz anderer Leute, die diese Leute frei zur Verfügung stellen.
Dafür müssen die eigenen Möglichkeiten gar nicht besonders groß sein (wie gesagt, ich kann kein VBS und fast jeder andere, der gar nichts programmieren kann, könnte den Scanner mit dem Script andere Sachen sprechen lassen).
Worum es mir hier eigentlich geht ist also nicht vorzustellen, dass der Scanner jetzt sprechen kann (das habe ich dem Scanner als Programmierer nie beigebracht), sondern die Vorstellung eines Konzeptes, was sich Können und Wissen von überall herholen kann - egal ob es das Sprechen oder sonstwas ist.
...schaust du dir aber das Script an, was spricht, ist bereits ohne irgendetwas programmieren zu können wohl offensichtlich, was man genau ändern muss, um andere Sachen sprechen zu lassen. Lesen zu können reicht da eigentlich aus.
Dessen bin ich mir bewusst. Ich denke wir reden hier etwas aneinander vorbei. Das ich die Sätze tauschen kann weiß ich, steht ja auch da, dazu muss man nur lesen. Darum ging es mir gar nicht.
Kann schon sein.
Wenn du darauf hinaus willst: Um die Sprache zu testen, musst du keine Scripte schreiben. Die Sprache ist in einigen mitgelieferten Scripten drin, die über das Menü ausgeführt werden können.
Was mir wichtig ist:
Obwohl das Ausführen von Sprache etwas recht komplexes ist, wurde niemals in den Code des Scanner eingebaut, dass er sprechen kann. Sprechen kann er aber trotzdem. Er spricht über ein spezielles Script. Er spricht auch nicht irgendwas, sondern weil dieses Script abhängig mit dem Rest, was der Scanner da tut, verknüpft ist (siehe Video), spricht er genau das, was dort in dem Augenblick zu dem passt, was er da tut.
Ein "Pluginbeispiel" um zu zeigen, wie mächtig das sein kann:
Der Scanner ist nie dafür programmiert worden, Textausdrücke im Speicher eines laufenden Programmes zu sammeln. Bei der Analyse von Malware kann das aber manchmal recht nützlich sein. Über folgendes Script kann man den Scanner etwas tun lassen, was er eigentlich gar nicht kann:
SET_ENV_VAR->PPFS_ProcessID>0
FILE_EXISTS_TO_ENV_VAR->%Systemroot%\System32\WindowsPowerShell\v1.0\powershell.exe>PPFS_PowershellExists
If->%PPFS_PowershellExists%=1
InputDIALOG->ProcessID
->Hier bitte einen Prozess wählen und OK klicken, um den Prozessspeicher nach Strings zu durchsuchen!
->
->PPFS_ProcessID
END_IF->
If->%PPFS_ProcessID%<>0
CREATE_FOLDER->C:\PPFS_T
CREATE_FOLDER->C:\PPF_Scan1
CREATE_BATCH_FILE->C:\PPFS_T\GetProcessStrings.ps1
WRITE_BATCH->Remove-Item C:\PPFS_T\Ready.txt
WRITE_BATCH->function Check-MemoryProtection
WRITE_BATCH->{
WRITE_BATCH->##################################################################
WRITE_BATCH->#.Synopsis
WRITE_BATCH-># Retrieves the memory protections of an arbitrary address.
WRITE_BATCH->#
WRITE_BATCH-># Author: Matthew Graeber (@mattifestation)
WRITE_BATCH-># License: GNU GPL v2
WRITE_BATCH->#.Description
WRITE_BATCH-># The Check-MemoryProtection cmdlet returns the memory protections of any memory address.
WRITE_BATCH->#
WRITE_BATCH-># Check-MemoryProtection is just a wrapper for the Windows API VirtualQuery function that outputs protections in a human-readable format.
WRITE_BATCH->#.Parameter Address
WRITE_BATCH-># Specifies the address whose memory protections are to be queried.
WRITE_BATCH->#.Parameter ProcessId
WRITE_BATCH-># Queries the memory of the provided process ID.
WRITE_BATCH->#.Parameter PageSize
WRITE_BATCH-># Specifies the memory page size. This can safely be left to its default of 0x1000 bytes.
WRITE_BATCH->#.Outputs
WRITE_BATCH-># Winapi.Kernel32+MEMORY_BASIC_INFORMATION
WRITE_BATCH-># By default, Check-MemoryProtection returns a MEMORY_BASIC_INFORMATION structure.
WRITE_BATCH->#.Example
WRITE_BATCH-># C:\PS>$proc = [System.Diagnostics.Process]::GetCurrentProcess()
WRITE_BATCH->#
WRITE_BATCH-># C:\PS>$module = $proc.MainModule
WRITE_BATCH->#
WRITE_BATCH-># C:\PS>$base = $module.BaseAddress
WRITE_BATCH->#
WRITE_BATCH-># C:\PS>Check-MemoryProtection $base
WRITE_BATCH->#
WRITE_BATCH-># BaseAddress : 5363597312
WRITE_BATCH-># AllocationBase : 5363597312
WRITE_BATCH-># AllocationProtect : PAGE_EXECUTE_WRITECOPY
WRITE_BATCH-># RegionSize : 4096
WRITE_BATCH-># State : MEM_COMMIT
WRITE_BATCH-># Protect : PAGE_READONLY
WRITE_BATCH-># Type : MEM_IMAGE
WRITE_BATCH->#
WRITE_BATCH->#
WRITE_BATCH-># Description
WRITE_BATCH-># -----------
WRITE_BATCH-># This command returns the memory protections of the currently loaded process' base address. In this example, the memory address queried is the base address of powershell.exe
WRITE_BATCH->#.Example
WRITE_BATCH-># C:\PS>$proc = ps cmd
WRITE_BATCH->#
WRITE_BATCH-># C:\PS>$base = $proc.MainModule.BaseAddress
WRITE_BATCH->#
WRITE_BATCH-># C:\PS>Check-MemoryProtection $base $proc.Id
WRITE_BATCH->#
WRITE_BATCH-># BaseAddress : 1246035968
WRITE_BATCH-># AllocationBase : 1246035968
WRITE_BATCH-># AllocationProtect : PAGE_EXECUTE_WRITECOPY
WRITE_BATCH-># RegionSize : 4096
WRITE_BATCH-># State : MEM_COMMIT
WRITE_BATCH-># Protect : PAGE_READONLY
WRITE_BATCH-># Type : MEM_IMAGE
WRITE_BATCH->#
WRITE_BATCH->#
WRITE_BATCH-># Description
WRITE_BATCH-># -----------
WRITE_BATCH-># This command returns the memory protections of cmd.exe.
WRITE_BATCH->#.Example
WRITE_BATCH-># C:\PS>Check-MemoryProtection 0x00000000
WRITE_BATCH->#
WRITE_BATCH-># BaseAddress : 0
WRITE_BATCH-># AllocationBase : 0
WRITE_BATCH-># AllocationProtect : 0
WRITE_BATCH-># RegionSize : 65536
WRITE_BATCH-># State : MEM_FREE
WRITE_BATCH-># Protect : PAGE_NOACCESS
WRITE_BATCH-># Type : 0
WRITE_BATCH->#
WRITE_BATCH->#
WRITE_BATCH-># Description
WRITE_BATCH-># -----------
WRITE_BATCH-># This command returns the memory protections of the null page.
WRITE_BATCH->#.Link
WRITE_BATCH-># My blog: http://www.exploit-monday.com/
WRITE_BATCH-># MEMORY_BASIC_INFORMATION structure info: http://msdn.microsoft.com/en-us/library/windows/desktop/aa366775(v=vs.85).aspx
WRITE_BATCH->##################################################################
WRITE_BATCH-> [CmdletBinding()] Param (
WRITE_BATCH-> [Parameter(Position = 0, Mandatory = $True)] [System.IntPtr] $Address,
WRITE_BATCH-> [Parameter(Position = 1)] [Int] $ProcessId,
WRITE_BATCH-> [Parameter(Position = 2)] [Int] $PageSize = 0x1000
WRITE_BATCH-> )
WRITE_BATCH-> try
WRITE_BATCH-> {
WRITE_BATCH-> $mem = New-Object Winapi.Kernel32+MEMORY_BASIC_INFORMATION
WRITE_BATCH-> }
WRITE_BATCH-> catch
WRITE_BATCH-> {
WRITE_BATCH-> $code = @"
WRITE_BATCH-> using System;
WRITE_BATCH-> using System.Runtime.InteropServices;
WRITE_BATCH->
WRITE_BATCH-> namespace Winapi
WRITE_BATCH-> {
WRITE_BATCH-> public class Kernel32
WRITE_BATCH-> {
WRITE_BATCH-> [Flags]
WRITE_BATCH-> public enum ProcessAccessFlags : uint
WRITE_BATCH-> {
WRITE_BATCH-> PROCESS_VM_READ = 0x00000010,
WRITE_BATCH-> PROCESS_QUERY_INFORMATION = 0x00000400,
WRITE_BATCH-> ALL = 0x001F0FFF
WRITE_BATCH-> }
WRITE_BATCH-> [Flags]
WRITE_BATCH-> public enum AllocationProtectEnum : uint
WRITE_BATCH-> {
WRITE_BATCH-> PAGE_EXECUTE = 0x00000010,
WRITE_BATCH-> PAGE_EXECUTE_READ = 0x00000020,
WRITE_BATCH-> PAGE_EXECUTE_READWRITE = 0x00000040,
WRITE_BATCH-> PAGE_EXECUTE_WRITECOPY = 0x00000080,
WRITE_BATCH-> PAGE_NOACCESS = 0x00000001,
WRITE_BATCH-> PAGE_READONLY = 0x00000002,
WRITE_BATCH-> PAGE_READWRITE = 0x00000004,
WRITE_BATCH-> PAGE_WRITECOPY = 0x00000008,
WRITE_BATCH-> PAGE_GUARD = 0x00000100,
WRITE_BATCH-> PAGE_NOCACHE = 0x00000200,
WRITE_BATCH-> PAGE_WRITECOMBINE = 0x00000400,
WRITE_BATCH-> }
WRITE_BATCH-> [Flags]
WRITE_BATCH-> public enum StateEnum : uint
WRITE_BATCH-> {
WRITE_BATCH-> MEM_COMMIT = 0x00001000,
WRITE_BATCH-> MEM_FREE = 0x00010000,
WRITE_BATCH-> MEM_RESERVE = 0x00002000,
WRITE_BATCH-> }
WRITE_BATCH-> [Flags]
WRITE_BATCH-> public enum TypeEnum : uint
WRITE_BATCH-> {
WRITE_BATCH-> MEM_IMAGE = 0x01000000,
WRITE_BATCH-> MEM_MAPPED = 0x00040000,
WRITE_BATCH-> MEM_PRIVATE = 0x00020000,
WRITE_BATCH-> }
WRITE_BATCH-> [StructLayout(LayoutKind.Sequential)]
WRITE_BATCH-> public struct MEMORY_BASIC_INFORMATION
WRITE_BATCH-> {
WRITE_BATCH-> public IntPtr BaseAddress;
WRITE_BATCH-> public IntPtr AllocationBase;
WRITE_BATCH-> public AllocationProtectEnum AllocationProtect;
WRITE_BATCH-> public IntPtr RegionSize;
WRITE_BATCH-> public StateEnum State;
WRITE_BATCH-> public AllocationProtectEnum Protect;
WRITE_BATCH-> public TypeEnum Type;
WRITE_BATCH-> }
WRITE_BATCH->
WRITE_BATCH-> [DllImport("kernel32.dll")]
WRITE_BATCH-> public static extern IntPtr OpenProcess(ProcessAccessFlags dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, uint dwProcessId);
WRITE_BATCH-> [DllImport("kernel32.dll")]
WRITE_BATCH-> public static extern int VirtualQuery(IntPtr lpAddress, ref MEMORY_BASIC_INFORMATION lpBuffer, int dwLength);
WRITE_BATCH-> [DllImport("kernel32.dll")]
WRITE_BATCH-> public static extern int VirtualQueryEx(IntPtr hProcess, IntPtr lpAddress, ref MEMORY_BASIC_INFORMATION lpBuffer, int dwLength);
WRITE_BATCH-> [DllImport("kernel32.dll")]
WRITE_BATCH-> public static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, [Out, MarshalAs(UnmanagedType.AsAny)] object lpBuffer, int dwSize, [Out] int lpNumberOfBytesRead);
WRITE_BATCH-> [DllImport("kernel32.dll")]
WRITE_BATCH-> public static extern bool CloseHandle(IntPtr hObject);
WRITE_BATCH-> }
WRITE_BATCH-> }
WRITE_BATCH->"@
WRITE_BATCH->
WRITE_BATCH-> $codeProvider = New-Object Microsoft.CSharp.CSharpCodeProvider
WRITE_BATCH-> $location = [PsObject].Assembly.Location
WRITE_BATCH-> $compileParams = New-Object System.CodeDom.Compiler.CompilerParameters
WRITE_BATCH-> $assemblyRange = @("System.dll", $location)
WRITE_BATCH-> $compileParams.ReferencedAssemblies.AddRange($assemblyRange)
WRITE_BATCH-> $compileParams.GenerateInMemory = $True
WRITE_BATCH-> $codeProvider.CompileAssemblyFromSource($compileParams, $code) | Out-Null
WRITE_BATCH-> }
WRITE_BATCH->
WRITE_BATCH-> $mem = New-Object Winapi.Kernel32+MEMORY_BASIC_INFORMATION
WRITE_BATCH->
WRITE_BATCH-> if ($ProcessId)
WRITE_BATCH-> {
WRITE_BATCH-> $ProcHandle = [Winapi.Kernel32]::OpenProcess([Winapi.Kernel32+ProcessAccessFlags]::PROCESS_QUERY_INFORMATION, 0, $ProcessId)
WRITE_BATCH-> [Winapi.Kernel32]::VirtualQueryEx($ProcHandle, $Address, [ref] $mem, $PageSize) | Out-Null
WRITE_BATCH-> [Winapi.Kernel32]::CloseHandle($ProcHandle) | Out-Null
WRITE_BATCH-> }
WRITE_BATCH-> else
WRITE_BATCH-> {
WRITE_BATCH-> [Winapi.Kernel32]::VirtualQuery($Address, [ref] $mem, $PageSize) | Out-Null
WRITE_BATCH-> }
WRITE_BATCH-> return $mem
WRITE_BATCH->}
WRITE_BATCH->
WRITE_BATCH->function Dump-Memory
WRITE_BATCH->{
WRITE_BATCH->##################################################################
WRITE_BATCH->#.Synopsis
WRITE_BATCH-># Dumps memory contents to stdout or to disk.
WRITE_BATCH->#
WRITE_BATCH-># Author: Matthew Graeber (@mattifestation)
WRITE_BATCH-># License: GNU GPL v2
WRITE_BATCH->#.Description
WRITE_BATCH-># The Dump-Memory cmdlet displays the contents of memory to stdout. You also have the option to dump raw memory to disk.
WRITE_BATCH->#.Parameter Address
WRITE_BATCH-># Specifies the base address of memory that is to be dumped.
WRITE_BATCH->#.Parameter Offset
WRITE_BATCH-># Specifies the number of bytes to dump.
WRITE_BATCH->#.Parameter ProcessId
WRITE_BATCH-># Dumps the memory of the process whose ID was specified.
WRITE_BATCH->#.Parameter Width
WRITE_BATCH-># Specifies how many bytes to print per line when outputting to stdout
WRITE_BATCH->#.Parameter DumpToFile
WRITE_BATCH-># Specifies the path to the output file.
WRITE_BATCH->#
WRITE_BATCH-># When this option is specified, memory will not be displayed on stdout.
WRITE_BATCH->#
WRITE_BATCH-># This parameter can be in the for of an absolute or relative file path.
WRITE_BATCH->#.Example
WRITE_BATCH-># $proc = ps cmd
WRITE_BATCH->#
WRITE_BATCH-># $module = $proc.MainModule
WRITE_BATCH->#
WRITE_BATCH-># $base = $module.BaseAddress
WRITE_BATCH->#
WRITE_BATCH-># Dump-Memory $base 0x98 -ProcessId $proc.Id
WRITE_BATCH->#
WRITE_BATCH-># 00000000h 4D 5A 90 00 03 00 00 00 04 00 00 00 FF FF 00 00 MZ..........ÿÿ..
WRITE_BATCH-># 00000010h B8 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00 ,.......@.......
WRITE_BATCH-># 00000020h 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
WRITE_BATCH-># 00000030h 00 00 00 00 00 00 00 00 00 00 00 00 F0 00 00 00 ............d...
WRITE_BATCH-># 00000040h 0E 1F BA 0E 00 B4 09 CD 21 B8 01 4C CD 21 54 68 ..º..'.I!,.LI!Th
WRITE_BATCH-># 00000050h 69 73 20 70 72 6F 67 72 61 6D 20 63 61 6E 6E 6F is.program.canno
WRITE_BATCH-># 00000060h 74 20 62 65 20 72 75 6E 20 69 6E 20 44 4F 53 20 t.be.run.in.DOS.
WRITE_BATCH-># 00000070h 6D 6F 64 65 2E 0D 0D 0A 24 00 00 00 00 00 00 00 mode....$.......
WRITE_BATCH-># 00000080h 4D 7C A4 8A 09 1D CA D9 09 1D CA D9 09 1D CA D9 M|¤...EU..EU..EU
WRITE_BATCH-># 00000090h 00 65 4E D9 08 1D CA D9 .eNU..EU
WRITE_BATCH->#
WRITE_BATCH->#
WRITE_BATCH-># Description
WRITE_BATCH-># -----------
WRITE_BATCH-># This command dumps the first 0x98 bytes of the main module of cmd.exe to stdout.
WRITE_BATCH->#.Example
WRITE_BATCH-># C:\PS>$proc = [System.Diagnostics.Process]::GetCurrentProcess()
WRITE_BATCH->#
WRITE_BATCH-># C:\PS>$module = $proc.MainModule
WRITE_BATCH->#
WRITE_BATCH-># C:\PS>$base = $module.BaseAddress
WRITE_BATCH->#
WRITE_BATCH-># C:\PS>Dump-Memory $base 0x120
WRITE_BATCH->#
WRITE_BATCH-># 00000000h 4D 5A 90 00 03 00 00 00 04 00 00 00 FF FF 00 00 MZ..........ÿÿ..
WRITE_BATCH-># 00000010h B8 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00 ,.......@.......
WRITE_BATCH-># 00000020h 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
WRITE_BATCH-># 00000030h 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 ................
WRITE_BATCH-># 00000040h 0E 1F BA 0E 00 B4 09 CD 21 B8 01 4C CD 21 54 68 ..º..'.I!,.LI!Th
WRITE_BATCH-># 00000050h 69 73 20 70 72 6F 67 72 61 6D 20 63 61 6E 6E 6F is.program.canno
WRITE_BATCH-># 00000060h 74 20 62 65 20 72 75 6E 20 69 6E 20 44 4F 53 20 t.be.run.in.DOS.
WRITE_BATCH-># 00000070h 6D 6F 64 65 2E 0D 0D 0A 24 00 00 00 00 00 00 00 mode....$.......
WRITE_BATCH-># 00000080h FF 54 CD 72 BB 35 A3 21 BB 35 A3 21 BB 35 A3 21 ÿTIr»5£!»5£!»5£!
WRITE_BATCH-># 00000090h 9C F3 D8 21 B9 35 A3 21 B2 4D 36 21 BA 35 A3 21 .óO!.5£!.M6!º5£!
WRITE_BATCH-># 000000A0h B2 4D 27 21 AB 35 A3 21 B2 4D 30 21 AA 35 A3 21 .M'!«5£!.M0!ª5£!
WRITE_BATCH-># 000000B0h BB 35 A2 21 20 35 A3 21 B2 4D 20 21 FF 35 A3 21 »5¢!.5£!.M.!ÿ5£!
WRITE_BATCH-># 000000C0h B2 4D 29 21 BD 35 A3 21 9C F3 DD 21 BA 35 A3 21 .M)!.5£!.óY!º5£!
WRITE_BATCH-># 000000D0h B2 4D 37 21 BA 35 A3 21 B2 4D 32 21 BA 35 A3 21 .M7!º5£!.M2!º5£!
WRITE_BATCH-># 000000E0h 52 69 63 68 BB 35 A3 21 00 00 00 00 00 00 00 00 Rich»5£!........
WRITE_BATCH-># 000000F0h 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
WRITE_BATCH-># 00000100h 50 45 00 00 64 86 05 00 F3 C7 5B 4A 00 00 00 00 PE..d...óÇ[J....
WRITE_BATCH-># 00000110h 00 00 00 00 F0 00 22 00 0B 02 09 00 00 DC 00 00 ....d."......Ü..
WRITE_BATCH->#
WRITE_BATCH->#
WRITE_BATCH-># Description
WRITE_BATCH-># -----------
WRITE_BATCH-># This command dumps the first 0x120 bytes of the main module of the currently loaded process (powershell.exe) to stdout.
WRITE_BATCH->#.Example
WRITE_BATCH-># C:\PS>$proc = [System.Diagnostics.Process]::GetCurrentProcess()
WRITE_BATCH->#
WRITE_BATCH-># C:\PS>$module = $proc.MainModule
WRITE_BATCH->#
WRITE_BATCH-># C:\PS>$size = $module.ModuleMemorySize
WRITE_BATCH->#
WRITE_BATCH-># C:\PS>$base = $module.BaseAddress
WRITE_BATCH->#
WRITE_BATCH-># C:\PS>Dump-Memory $base $size -DumpToFile .\out.exe
WRITE_BATCH->#
WRITE_BATCH->#
WRITE_BATCH-># Description
WRITE_BATCH-># -----------
WRITE_BATCH-># This command dumps the entire memory image of powershell.exe to disk in binary format.
WRITE_BATCH->#
WRITE_BATCH-># Note: Execution of the dumped memory image requires fixing up the PE header.
WRITE_BATCH->#.Link
WRITE_BATCH-># My blog: http://www.exploit-monday.com/
WRITE_BATCH->##################################################################
WRITE_BATCH-> [CmdletBinding()] Param (
WRITE_BATCH-> [Parameter(Position = 0, Mandatory = $True)] [System.IntPtr] $Address,
WRITE_BATCH-> [Parameter(Position = 1, Mandatory = $True)] [Int] $Offset,
WRITE_BATCH-> [Parameter()] [Int] $ProcessId,
WRITE_BATCH-> [Parameter()] [Int] $Width = 16,
WRITE_BATCH-> [Parameter()] [String] $DumpToFile
WRITE_BATCH-> )
WRITE_BATCH-> $BaseAddress = $Address.ToInt64()
WRITE_BATCH-> for ($PageOffset = 0; $PageOffset -lt $Offset; $PageOffset += 0x1000)
WRITE_BATCH-> {
WRITE_BATCH-> $PageBaseAddress = [IntPtr]($BaseAddress + $PageOffset)
WRITE_BATCH-> if ($ProcessId)
WRITE_BATCH-> {
WRITE_BATCH-> $MemProtect = Check-MemoryProtection $PageBaseAddress $ProcessId
WRITE_BATCH-> }
WRITE_BATCH-> else
WRITE_BATCH-> {
WRITE_BATCH-> $MemProtect = Check-MemoryProtection $PageBaseAddress
WRITE_BATCH-> }
WRITE_BATCH-> if ($MemProtect.Protect -eq [Winapi.Kernel32+AllocationProtectEnum]::PAGE_NOACCESS)
WRITE_BATCH-> {
WRITE_BATCH-> throw "Memory region at base address 0x$($PageBaseAddress.ToString('X16')) is inaccessible!`n `nMemory Protection Information:`n$($MemProtect | Out-String)`n `n"
WRITE_BATCH-> }
WRITE_BATCH-> }
WRITE_BATCH-> [Byte[]] $ByteArray = New-Object Byte[]($Offset)
WRITE_BATCH-> if ($ProcessId)
WRITE_BATCH-> {
WRITE_BATCH-> $BytesRead = 0
WRITE_BATCH-> $ProcHandle = [Winapi.Kernel32]::OpenProcess(([Winapi.Kernel32+ProcessAccessFlags]::PROCESS_VM_READ), 0, $ProcessId)
WRITE_BATCH-> [Winapi.Kernel32]::ReadProcessMemory($ProcHandle, $Address, $ByteArray, $Offset, $BytesRead) | Out-Null
WRITE_BATCH-> [Winapi.Kernel32]::CloseHandle($ProcHandle) | Out-Null
WRITE_BATCH-> }
WRITE_BATCH-> else
WRITE_BATCH-> {
WRITE_BATCH-> [System.Runtime.InteropServices.Marshal]::Copy($Address, $ByteArray, 0, $Offset)
WRITE_BATCH-> }
WRITE_BATCH-> $Position = 0
WRITE_BATCH-> $Padding = ($Width * 2) + $Width
WRITE_BATCH-> if($DumpToFile)
WRITE_BATCH-> {
WRITE_BATCH-> if ($FilePath = Split-Path $DumpToFile)
WRITE_BATCH-> {
WRITE_BATCH-> if (Test-Path $FilePath)
WRITE_BATCH-> {
WRITE_BATCH-> $File = "$(Resolve-Path $FilePath)\$DumpToFile"
WRITE_BATCH-> }
WRITE_BATCH-> else
WRITE_BATCH-> {
WRITE_BATCH-> throw "Invalid file path!"
WRITE_BATCH-> }
WRITE_BATCH-> }
WRITE_BATCH-> else
WRITE_BATCH-> {
WRITE_BATCH-> $File = "$(Resolve-Path .)\$DumpToFile"
WRITE_BATCH-> }
WRITE_BATCH-> $Stream = New-Object System.IO.FileStream($File, [System.IO.FileMode]::Create)
WRITE_BATCH-> $Stream.Write($ByteArray, 0, $Offset)
WRITE_BATCH-> $Stream.Close()
WRITE_BATCH-> }
WRITE_BATCH-> else
WRITE_BATCH-> {
WRITE_BATCH-> while ($Position -le ($Offset-1))
WRITE_BATCH-> {
WRITE_BATCH-> $Line = ""
WRITE_BATCH->
WRITE_BATCH-> $Line = "$($Position.ToString('X8'))h "
WRITE_BATCH-> $PrintBytes = ""
WRITE_BATCH-> $Text = ""
WRITE_BATCH->
WRITE_BATCH-> foreach ($i in 0..($Width-1))
WRITE_BATCH-> {
WRITE_BATCH-> if ($Position -ge $Offset) {break}
WRITE_BATCH-> $PrintBytes += "$($ByteArray[$Position].ToString('X2')) "
WRITE_BATCH->
WRITE_BATCH-> if ( [Char]::IsLetterOrDigit($ByteArray[$Position]) -or [Char]::IsPunctuation($ByteArray[$Position]) -or [Char]::IsSymbol($ByteArray[$Position]) )
WRITE_BATCH-> {
WRITE_BATCH-> $Text += [Char] $ByteArray[$Position]
WRITE_BATCH-> }
WRITE_BATCH-> else
WRITE_BATCH-> {
WRITE_BATCH-> $Text += '.'
WRITE_BATCH-> }
WRITE_BATCH-> $Position++
WRITE_BATCH-> }
WRITE_BATCH->
WRITE_BATCH-> $Line += $PrintBytes.PadRight($Padding, ' ')
WRITE_BATCH-> $Line += " $Text"
WRITE_BATCH->
WRITE_BATCH-> $Line
WRITE_BATCH-> }
WRITE_BATCH-> }
WRITE_BATCH->}
WRITE_BATCH->
WRITE_BATCH->function Dump-Strings
WRITE_BATCH->{
WRITE_BATCH->##################################################################
WRITE_BATCH->#.Synopsis
WRITE_BATCH-># Retrieves strings from memory.
WRITE_BATCH->#
WRITE_BATCH-># Author: Matthew Graeber (@mattifestation)
WRITE_BATCH-># License: GNU GPL v2
WRITE_BATCH->#.Description
WRITE_BATCH-># The Dump-Strings cmdlet retrieves strings from the memory of any process.
WRITE_BATCH->#
WRITE_BATCH-># Dump-Strings will print both ASCII and Unicode strings to stdout. Its functionality is similar to Sysinternals strings.exe but it operates in memory.
WRITE_BATCH->#.Parameter Address
WRITE_BATCH-># Specifies the memory base address.
WRITE_BATCH->#.Parameter Offset
WRITE_BATCH-># Specifies the number of bytes to process.
WRITE_BATCH->#.Parameter ProcessId
WRITE_BATCH-># Dumps the strings of the process whose ID was specified. Not specifying a process ID will result in querying the address space of powershell.exe.
WRITE_BATCH->#.Parameter Encoding
WRITE_BATCH-># Specifies the string encoding to use. The default option is 'DEFAULT' which will return both ASCII and Unicode. The other options are 'ASCII' and 'UNICODE'
WRITE_BATCH->#.Parameter MinimumLength
WRITE_BATCH-># Specifies the minimum length string to return. The default length is 3.
WRITE_BATCH->#.Parameter StringOffset
WRITE_BATCH-># Specifies the offset in memory where the string occurs.
WRITE_BATCH->#.Example
WRITE_BATCH-># C:\PS>$proc = Get-Process cmd
WRITE_BATCH->#
WRITE_BATCH-># C:\PS>$module = $proc.MainModule
WRITE_BATCH->#
WRITE_BATCH-># C:\PS>$size = $module.ModuleMemorySize
WRITE_BATCH->#
WRITE_BATCH-># C:\PS>$base = $module.BaseAddress
WRITE_BATCH->#
WRITE_BATCH-># C:\PS>Dump-Strings $base $size -MinimumLength 20 -ProcessId $proc.Id
WRITE_BATCH->#
WRITE_BATCH-># !This program cannot be run in DOS mode.
WRITE_BATCH-># api-ms-win-core-processthreads-l1-1-0.DLL
WRITE_BATCH-># SetConsoleInputExeNameW
WRITE_BATCH-># APerformUnaryOperation: '%c'
WRITE_BATCH-># APerformArithmeticOperation: '%c'
WRITE_BATCH-># NtQueryInformationProcess
WRITE_BATCH-># SaferComputeTokenFromLevel
WRITE_BATCH-># ImpersonateLoggedOnUser
WRITE_BATCH-># SaferRecordEventLogEntry
WRITE_BATCH-># CreateProcessAsUserW
WRITE_BATCH-># GetSecurityDescriptorOwner
WRITE_BATCH-># WNetCancelConnection2W
WRITE_BATCH-># __C_specific_handler
WRITE_BATCH-># RtlLookupFunctionEntry
WRITE_BATCH-># ...
WRITE_BATCH->#
WRITE_BATCH->#
WRITE_BATCH-># Description
WRITE_BATCH-># -----------
WRITE_BATCH-># This command prints all Ascii and Unicode strings of length > 19 in the memory space of the main module of cmd.exe.
WRITE_BATCH->#.Example
WRITE_BATCH-># C:\PS>$proc = [System.Diagnostics.Process]::GetCurrentProcess()
WRITE_BATCH->#
WRITE_BATCH-># C:\PS>$module = $proc.Modules | ? { $_.ModuleName -eq 'ntdll.dll' }
WRITE_BATCH->#
WRITE_BATCH-># C:\PS>$size = $module.ModuleMemorySize
WRITE_BATCH->#
WRITE_BATCH-># C:\PS>$base = $module.BaseAddress
WRITE_BATCH->#
WRITE_BATCH-># C:\PS>Dump-Strings $base $size -StringOffset -Encoding 'UNICODE'
WRITE_BATCH->#
WRITE_BATCH-># 57416:LdrResFallbackLangList Enter
WRITE_BATCH-># 57448:LdrResFallbackLangList Exit
WRITE_BATCH-># 136960:KnownDllPath
WRITE_BATCH-># 136976:\KnownDlls
WRITE_BATCH-># 136992:\SystemRoot
WRITE_BATCH-># 137008:\System32\
WRITE_BATCH-># 183672:\Registry\Machine\System\CurrentControlSet\Control\MUI\Settings
WRITE_BATCH-># 183736::%u.%u.%u.%u
WRITE_BATCH-># 183856:%u.%u.%u.%u
WRITE_BATCH-># 183872::%u
WRITE_BATCH-># 184048:RtlpResUltimateFallbackInfo Enter
WRITE_BATCH-># 184088:svchost.exe
WRITE_BATCH-># 184104:\Registry\Machine\Software\Microsoft\SQMClient\Windows\DisabledProcesses\
WRITE_BATCH-># 184184:GlobalSession
WRITE_BATCH-># 184200:\Registry\Machine\Software\Microsoft\SQMClient\Windows\DisabledSessions\
WRITE_BATCH->#
WRITE_BATCH->#
WRITE_BATCH-># Description
WRITE_BATCH-># -----------
WRITE_BATCH-># This command prints all Unicode strings of length > 2 in the loaded module - ntdll.dll within the memory space of powershell.exe.
WRITE_BATCH->#.Link
WRITE_BATCH-># My blog: http://www.exploit-monday.com/
WRITE_BATCH->##################################################################
WRITE_BATCH-> [CmdletBinding()] Param (
WRITE_BATCH-> [Parameter(Position = 0, Mandatory = $True)] [System.IntPtr] $Address,
WRITE_BATCH-> [Parameter(Position = 1, Mandatory = $True)] [Int] $Offset,
WRITE_BATCH-> [Parameter()] [Int] $ProcessId,
WRITE_BATCH-> [Parameter()] [String] $Encoding = 'DEFAULT',
WRITE_BATCH-> [Parameter()] [Int] $MinimumLength = 3,
WRITE_BATCH-> [Parameter()] [Switch] $StringOffset
WRITE_BATCH-> )
WRITE_BATCH-> $BaseAddress = $Address.ToInt64()
WRITE_BATCH-> for ($PageOffset = 0; $PageOffset -lt $Offset; $PageOffset += 0x1000)
WRITE_BATCH-> {
WRITE_BATCH-> $PageBaseAddress = [IntPtr]($BaseAddress + $PageOffset)
WRITE_BATCH-> if ($ProcessId)
WRITE_BATCH-> {
WRITE_BATCH-> $MemProtect = Check-MemoryProtection $PageBaseAddress $ProcessId
WRITE_BATCH-> }
WRITE_BATCH-> else
WRITE_BATCH-> {
WRITE_BATCH-> $MemProtect = Check-MemoryProtection $PageBaseAddress
WRITE_BATCH-> }
WRITE_BATCH-> if ($MemProtect.Protect -eq [Winapi.Kernel32+AllocationProtectEnum]::PAGE_NOACCESS)
WRITE_BATCH-> {
WRITE_BATCH-> throw "Memory region at base address 0x$($PageBaseAddress.ToString('X16')) is inaccessible!`n `nMemory Protection Information:`n$($MemProtect | Out-String)`n `n"
WRITE_BATCH-> }
WRITE_BATCH-> }
WRITE_BATCH-> [Byte[]] $ByteArray = New-Object Byte[]($Offset)
WRITE_BATCH-> if ($ProcessId)
WRITE_BATCH-> {
WRITE_BATCH-> $BytesRead = 0
WRITE_BATCH-> $ProcHandle = [Winapi.Kernel32]::OpenProcess(([Winapi.Kernel32+ProcessAccessFlags]::PROCESS_VM_READ), 0, $ProcessId)
WRITE_BATCH-> [Winapi.Kernel32]::ReadProcessMemory($ProcHandle, $Address, $ByteArray, $Offset, $BytesRead) | Out-Null
WRITE_BATCH-> [Winapi.Kernel32]::CloseHandle($ProcHandle) | Out-Null
WRITE_BATCH-> }
WRITE_BATCH-> else
WRITE_BATCH-> {
WRITE_BATCH-> [System.Runtime.InteropServices.Marshal]::Copy($Address, $ByteArray, 0, $Offset)
WRITE_BATCH-> }
WRITE_BATCH-> if ($Encoding.ToUpper() -eq 'DEFAULT')
WRITE_BATCH-> { # This hack will get the raw ascii chars. The System.Text.UnicodeEncoding object will replace some unprintable chars with question marks.
WRITE_BATCH-> $ArrayPtr = [System.Runtime.InteropServices.Marshal]::UnsafeAddrOfPinnedArrayElement($ByteArray, 0)
WRITE_BATCH-> $RawString = [System.Runtime.InteropServices.Marshal]::PtrToStringAnsi($ArrayPtr, $ByteArray.Length)
WRITE_BATCH-> $Regex = [regex] "[\x20-\x7E]{$MinimumLength,}"
WRITE_BATCH-> $Results = $Regex.Matches($RawString)
WRITE_BATCH-> # Unicode Regex
WRITE_BATCH-> $Encoder = New-Object System.Text.UnicodeEncoding
WRITE_BATCH-> $RawString = $Encoder.GetString($ByteArray, 0, $Offset)
WRITE_BATCH-> $Regex = [regex] "[\u0020-\u007E]{$MinimumLength,}"
WRITE_BATCH-> $Results += $Regex.Matches($RawString)
WRITE_BATCH-> }
WRITE_BATCH-> elseif ($Encoding.ToUpper() -eq 'ASCII')
WRITE_BATCH-> { # This hack will get the raw ascii chars. The System.Text.UnicodeEncoding object will replace some unprintable chars with question marks.
WRITE_BATCH-> $ArrayPtr = [System.Runtime.InteropServices.Marshal]::UnsafeAddrOfPinnedArrayElement($ByteArray, 0)
WRITE_BATCH-> $RawString = [System.Runtime.InteropServices.Marshal]::PtrToStringAnsi($ArrayPtr, $ByteArray.Length)
WRITE_BATCH-> $Regex = [regex] "[\x20-\x7E]{$MinimumLength,}"
WRITE_BATCH-> $Results = $Regex.Matches($RawString)
WRITE_BATCH-> }
WRITE_BATCH-> else
WRITE_BATCH-> { # Unicode Regex
WRITE_BATCH-> $Encoder = New-Object System.Text.UnicodeEncoding
WRITE_BATCH-> $RawString = $Encoder.GetString($ByteArray, 0, $Offset)
WRITE_BATCH-> $Regex = [regex] "[\u0020-\u007E]{$MinimumLength,}"
WRITE_BATCH-> $Results = $Regex.Matches($RawString)
WRITE_BATCH-> }
WRITE_BATCH-> if ($StringOffset)
WRITE_BATCH-> {
WRITE_BATCH-> $Results | ForEach-Object { "$($_.Index):$($_.Value)" }
WRITE_BATCH-> }
WRITE_BATCH-> else
WRITE_BATCH-> {
WRITE_BATCH-> $Results | ForEach-Object { "$($_.Value)" }
WRITE_BATCH-> }
WRITE_BATCH->}
WRITE_BATCH->[int32]$ProcessID = [convert]::ToInt32($env:PPFS_ProcessID, 10)
WRITE_BATCH->Get-Process -Id $ProcessID | Out-File -FilePath C:\PPF_Scan1\ProcessStrings.txt -Encoding ASCII
WRITE_BATCH->$Headline = "_____________________________________________________________________________________________________"
WRITE_BATCH->Add-Content -Path C:\PPF_Scan1\ProcessStrings.txt -Value $Headline
WRITE_BATCH->Add-Content -Path C:\PPF_Scan1\ProcessStrings.txt -Value " "
WRITE_BATCH->Add-Content -Path C:\PPF_Scan1\ProcessStrings.txt -Value " "
WRITE_BATCH->[int]$Adresse = 0
WRITE_BATCH->[intPtr]$Adresse2 = 0
WRITE_BATCH->[int]$Size = 0
WRITE_BATCH->$ProtectProcess = Check-MemoryProtection $Adresse $ProcessID
WRITE_BATCH->while($ProtectProcess.RegionSize.ToInt64() -gt 0)
WRITE_BATCH->{
WRITE_BATCH-> $ProtectProcess = Check-MemoryProtection $Adresse $ProcessID
WRITE_BATCH-> if($ProtectProcess.Protect -eq [Winapi.Kernel32+AllocationProtectEnum]::PAGE_EXECUTE_READ -Or $ProtectProcess.Protect -eq [Winapi.Kernel32+AllocationProtectEnum]::PAGE_EXECUTE_READWRITE -Or $ProtectProcess.Protect -eq [Winapi.Kernel32+AllocationProtectEnum]::PAGE_READONLY -Or $ProtectProcess.Protect -eq [Winapi.Kernel32+AllocationProtectEnum]::PAGE_READWRITE -Or $ProtectProcess.Protect -eq [Winapi.Kernel32+AllocationProtectEnum]::PAGE_READWRITE)
WRITE_BATCH-> {
WRITE_BATCH-> $Adresse2 = [intPtr]$ProtectProcess.BaseAddress
WRITE_BATCH-> $Size = $ProtectProcess.RegionSize
WRITE_BATCH-> Dump-Strings $Adresse2 $Size -MinimumLength 5 -ProcessId $ProcessID | Out-File -Append -FilePath C:\PPF_Scan1\ProcessStrings.txt -Encoding ASCII
WRITE_BATCH-> }
WRITE_BATCH-> $Adresse = $Adresse + $ProtectProcess.RegionSize.ToInt64()
WRITE_BATCH->}
WRITE_BATCH->Set-Content -Path C:\PPFS_T\Ready.txt -Value "Ready"
START_SHELL->%Systemroot%\System32\WindowsPowerShell\v1.0\powershell.exe,-noprofile -noexit -executionpolicy bypass -file C:\PPFS_T\GetProcessStrings.ps1
SLEEP->30000
LOOP->0
FILE_EXISTS_TO_ENV_VAR->C:\PPFS_T\Ready.txt>Ready
IF->%Ready%=0
SLEEP->30000
END_IF->
IF->%Ready%=1
BREAK_LOOP->
END_IF->
END_LOOP->
CLOSE_SHELL->
COPY_SCANFILES->C:\PPF_Scan1
OPEN->C:\PPF_Scan1
END->
END_IF->
Alles anzeigen
Große Teile dieses Scriptes sind in Powershell geschrieben - wie man auch sieht, gar nicht von mir.
Führt man es aus, erscheint folgender Dialog:
[Blockierte Grafik: https://abload.de/img/18du6i.jpg]
Hier ist es möglich, einen Prozess auszuwählen und der Speicher des Prozesses wird danach auf Textausdrücke durchsucht und diese werden in einem LOG abgespeichert.
Im Prinzip ist das ein komplettes Programm mit grafischer Oberfläche. In dem was da eingebaut oder umgesetzt werden kann (und das, wie gesagt, von jedem, der etwas kann) sind da eigentlich keine Grenzen mehr gesetzt.
Vielleicht ist es eine große Hilfe für die User, die schlecht sehen oder Handycaps mit der
Tastatur haben, usw usw...
Richtig, Gerda!
Das wollte ich auch anmerken, gerade für Dich ist es eine große Hilfe.
Kann schon sein.
Wenn du darauf hinaus willst: Um die Sprache zu testen, musst du keine Scripte schreiben. Die Sprache ist in einigen mitgelieferten Scripten drin, die über das Menü ausgeführt werden können.
Ich will ja nichts am Script verändern oder sonstiges, sagte ja man hat da aneinender vorbeigeredet.
@Oldviking
Ja für viele ist es eine Hilfe aber wenn ein User schlecht sieht, dann kann er der Anleitung ebenso wenig folgen, hat sich ja aber geklärt was da kommt. Da es nur Hinweise laut AHT sind befürworte ich das Ganze, sofern die Übersetzung passt, anderseits bringt das Feature sonst nur den wenigsten was.
Das gute Weib spricht in einer App mit, da geht das wesentlich einfacher.
Der Scanner überprüft nun die erste im System installierte Sprache, ob diese Deutsch oder Englisch ist.
Ist sie Deutsch, quasselt er in Deutsch, ist sie Englisch quasselt er in Englisch. Kann er weder die Sprache Deutsch noch Englisch identifizieren, macht er das, was man eigentlich tun sollte, wenn man eine Sprache nicht kann:
Er hält vornehm die Klappe.
Das ganze ist, wie gesagt, ein Feature, um den User auf Sachen hinzuweisen, die er während eines Scans innerhalb eines Scriptes an einer ganz bestimmten Stelle nicht tun sollte oder nicht tun darf, damit alles klapp.
Der spricht also Hinweise in der Art:
Wäre es nicht möglich dem Scanner eine Audio-Datei abspielen zu lassen, eine die vielleicht sogar im PPF-Scan Ordner vorhanden ist?
Warum? Die Sprache ist in der Art an jedes Script anpassbar. Man kann ihn sprechen lassen, was gerade nötig ist und was man möchte. Wie gesagt - wenn einer möchte, kann er ihn auch Witze erzählen lassen. Was er spricht entscheidet derjenige, der das Script erstellt. Darum geht es ja - nicht ich entscheide, was der Scanner kann und tut, sondern derjenige, der ihn bedient oder bedienen lässt.
Konzept verstanden?
PS: In Windows10 ist übrigens neben Englisch auch Deutsch vorinstalliert. Die Sprache hört sich dort richtig gut an.
Wäre es nicht möglich dem Scanner eine Audio-Datei abspielen zu lassen, eine die vielleicht sogar im PPF-Scan Ordner vorhanden ist?
Natürlich kann man das. Schreibt aber irgendjemand anderes ein Script für den Scanner und möchte ihn zum Beispiel an einer bestimmten Stelle seines Scriptes sprechen lassen, dass der Internet-Browser während des Scans nicht bedient oder ausgeschaltet werden darf, kann er das nicht tun, weil er dafür erst einmal eine Sounddatei aufnehmen und im Scannerordner unterbringen lassen müsste.
Wie gesagt: Das ganze ist ein spezielles Konzept.
Verstehe. Denn sonst hätte ich dir jemanden zur Verfügung gestellt der die Hinweise vertont, Studioausrüstung vorhanden, dann hätte man eine saubere und qualitative Aufnahmen.
Genau das soll ja nicht sein. Unter Windows10 hört sich die Stimme wirklich sehr gut an. Es lohnt sich, den Scanner da mal mit dem Mitgelieferten Script Kernelmode RootKitscan.scp zu testen.
Es wäre in der Tat schlecht, das "vertonen" zu wollen. Jedesmal, wenn ein neuer Text gebraucht wird, wäre die "Dienstleistung" wieder notwendig. Außerdem wird der Download dann auch irgendwann nervig, weil das Ganze viel zu groß wird. Bleiben wir beim Witzeerzählen: Ein Witz nimmt als Text 1 KB ein. Wie groß wird die Audiodatei? Und das mal 100 und noch ein paar Meldungen dazu? Riesengroß.
Gruß Volkmar
Folgendes Script verwende ich zur Zeit zum Sprechen:
CREATE_FOLDER->C:\PPFS_T
CREATE_BATCH_FILE->C:\PPFS_T\Speak.vbs
WRITE_BATCH->Dim EnglishText, GermanText, VoiceName
WRITE_BATCH->EnglishText = "Information from PPF-Scan. "
WRITE_BATCH->EnglishText = EnglishText + "PPF-Scan wants to load files from the internet! "
WRITE_BATCH->EnglishText = EnglishText + "Pleace dont turn off internet connection! "
WRITE_BATCH->GermanText = "Information vom PPFScanner! "
WRITE_BATCH->GermanText = GermanText + "Der PPFScanner wird nun Dateien aus dem Internet herunterladen! "
WRITE_BATCH->GermanText = GermanText + "Bitte unterbrechen sie die Internetverbindung nicht, bis der Vorgang abgeschlossen ist! "
WRITE_BATCH->Set SAPI = CreateObject("SAPI.SpVoice")
WRITE_BATCH->Set SAPI.voice = SAPI.getvoices.item(0)
WRITE_BATCH->VoiceName = SAPI.GetVoices.item(0).GetDescription
WRITE_BATCH->VoiceName = ucase(VoiceName)
WRITE_BATCH->IF instr(1, VoiceName, "GERMAN", 0) > 0 Then
WRITE_BATCH-> SAPI.Speak GermanText
WRITE_BATCH->ElseIF instr(1, VoiceName, "DEUTSCH", 0) > 0 Then
WRITE_BATCH-> SAPI.Speak GermanText
WRITE_BATCH->ElseIF instr(1, VoiceName, "ENGLISH", 0) > 0 Then
WRITE_BATCH-> SAPI.Speak EnglishText
WRITE_BATCH->ElseIF instr(1, VoiceName, "ENGLISCH", 0) > 0 Then
WRITE_BATCH-> SAPI.Speak EnglishText
WRITE_BATCH->End If
START_SHELL->%SystemRoot%\system32\cmd.exe
EXECUTE_IN_SHELL->WSCRIPT.EXE C:\PPFS_T\Speak.vbs //B
CLOSE_SHELL->
Alles anzeigen
Grade mal angehört...
Die stimme klingt besser als in der Datei, die ich von dir hier liegen habe...doch wirklich was großes ist es nicht, da muss Microsoft verbessern, selbst Cortana klingt interessanter und flüssiger. Grade wenn man nebenbei noch am PC arbeitet ist es ziemlich nervig, muss aber jeder für sich selbst entscheiden.
Das ist eine Standardsprache - bessere Sprachen kosten oft Geld. Wie spricht er bei dir? deutsch oder englisch.
Bei mir spricht er deutsch, kanns aber mal auf meinem anderen System nachher versuchen => Ist auf englisch.
bessere Sprachen kosten oft Geld
Nicht unbedingt, solange es einem guten Zweck dient.
So - nochmals Update der Scripte hochgeladen. Ist der Windows Script Host (der dem PPFscanner als Host für die Sprache dient) deaktiviert, erkennt der Scanner das jetzt und führt Sprache nicht aus. Vorher erschien bei deaktiviertem Windows Script Host eine Fehlermeldung.
Beim Erstellen der Boot-DVD spricht er jetzt auch.
So lasse ich es erst mal, wenn durch die Sprachausgabe keine Probleme entstehen.
Die Sprache ist eigentlich nur eine kleine Spielerei - aber mit Hintergrund. Was ich hier testen möchte (denn bei Sprache fällt es sehr gut auf, wenn etwas nicht korrekt funktioniert), ist eine Art von "Plugin-Technik". Konzept der Sache ist es, den Scanner manche Sachen nicht mit eigenem Code ausführen zu lassen, sondern Code in lesbarer Form an andere Anwendungen weiterzuleiten und über diesen Code mit dieser anderen Anwendung zu kommunizieren. Die Sprache wird zum Beispiel von der Windows Komponente WSCript.exe ausgeführt. Der Code ist lesbarer VBSCript Code. Aber welche Vorteile bietet das?
Um einen Einblick zu geben, was ich persönlich unter "Plugin" verstehe, habe ich dem Paket des Scanners die Datei Strings aus Prozessspeicher lesen.scp beigefügt. Mit diesem Script lässt sich ein laufender Prozess auswählen. Der Scanner übergibt dann die PID des ausgewählten Prozesses und ein Powershell Script an die Powershell.exe. Powershell durchsucht daraufhin den Prozessspeicher des ausgewählten Prozesses auf Textausdrücke und listet die gefundenen Texte in einer Datei.
Sie haben noch kein Benutzerkonto auf unserer Seite? Registrieren Sie sich kostenlos und nehmen Sie an unserer Community teil!