Windowsユーザのための初めてのPerlプログラミング
ActivePerl (Windows版) には DynaLoader が付属しているので、今日からすぐに DynaLoader::dl_install_xsub を利用したプログラミングが出来ます。
簡単なメッセージボックスを表示するPerlプログラムは以下になります。
#!/usr/bin/perl use DynaLoader; sub GetProcAddress { my ($DLL, $API) = @_; my $path = "$ENV{SystemRoot}\\system32\\$DLL"; my $libref = DynaLoader::dl_load_file($path); pack "L", DynaLoader::dl_find_symbol($libref, $API); } my $x86 = "" . "h\0\0\0\0" . "h" . pack("P", "Message") . "h" . pack("P", "Hello, World!\n") . "h\0\0\0\0" . "\xb8" . GetProcAddress("user32.dll", "MessageBoxA") . "\xff\xd0" # call eax . "\xc3" # ret ; DynaLoader::dl_install_xsub("X",unpack"L",pack"P",$x86);&X;
このプログラム実行すると、「Hello, World!」と書かれたWindowsメッセージボックスが表示されます。
これを DynaLoader を使わない形に書き直すと以下のようになります。
#!/usr/bin/perl use strict; use warnings; use Win32::API; my $EnumWindows = Win32::API->new( "user32", "EnumWindows", "NN", "N" ); my $GetModuleHandle = Win32::API->new( "kernel32", "GetModuleHandleA", "P", "N" ); my $GetProcAddress = Win32::API->new( "kernel32", "GetProcAddress", "NP", "N" ); my $VirtualAlloc = Win32::API->new( "kernel32", "VirtualAlloc", "NNNN", "N" ); my $VirtualFree = Win32::API->new( "kernel32", "VirtualFree", "NNN", "N" ); my $RtlCopyMemory = Win32::API->new( "kernel32", "RtlMoveMemory", "NNN", "V" ); my $hUser32 = $GetModuleHandle->Call( "user32" ); my $MessageBox = $GetProcAddress->Call( $hUser32, "MessageBoxA" ); my $x86 = "" . "\x6a\0" # push 0 as MB_OK . "\x68" . pack( "P", "Message" ) # push caption . "\x68" . # push text pack( "p", "\x48\x65\x6c\x6c\x6f\x2c\x20\x8f\xba\x98\x61\x20\x57\x6f\x72\x6c\x64\x21" ) . "\x6a\0" # push 0 for HWND . "\xb8" . pack( "L", $MessageBox )# mov eax, func . "\xff\xd0" # call eax . "\x33\xc0" # xor eax, eax . "\xc2\x08\x00" # ret ; my $px86 = $VirtualAlloc->Call( 0, length( $x86 ), 0x1000, 0x40 ); $RtlCopyMemory->Call( $px86, unpack( 'L', pack( 'P', $x86 ) ), length( $x86 ) ); $EnumWindows->Call( $px86, 0 ); $VirtualFree->Call( $px86, 0, 0x8000 );
Win32::API はとっても便利なモジュールですね。
Perl 5.8.9 / 日本語 Windows Vista SP1 (x86) の環境で試しました。