はじめに
Windowsは拡張子exeじゃなくても実行できるよという話。
この記事の続編を書きました:WindowsのNTFS-ADSに存在する拡張子偽装されたexeを実行する話。
経緯
インストーラがたまにtmpファイルを実行しているのを見て、気になったのでとりあえず手元にあるexeファイルの拡張子をtmpにしてCreateProcessに食わせてみた
実行される側
適当にビルドされたものを
test.tmp
とか改名しておく(名前はなんでもいい。)
use winapi::um::winuser::{MessageBoxW, MB_OK};
use std::ptr;
fn main() {
unsafe {
MessageBoxW(
ptr::null_mut(), //hWnd: HWND
encode("Hello, World!").as_ptr(), //lpText: LPCWSTR
encode("こんにちわ、世界!").as_ptr(), //lpCaption: LPCWSTR
MB_OK); //uType: UINT
}
}
fn encode(source: &str) -> Vec<u16> {
source.encode_utf16().chain(Some(0)).collect()
}
実行する側
上記のtest.tmpを指定してCreateProcessするだけ。
system関数とかは一旦Shellを介するけど、CreateProcessは介さない。
直接プログラムのセクションをそのままメモリに配置するので実行ができるというだけの話。
使い方は
生成されたexe test.tmp ["引数"]
#include<windows.h>
#include<stdio.h>
int main(int argc,char* argv[]){
if(argc <=1 ){
printf("specify the \"program file path\" for argument.");
return -1;
}
char *program = NULL;
char *args = NULL;
if(argc>=2){program=argv[1];}
if(argc>=3){args=argv[2];}
STARTUPINFO info = {sizeof(STARTUPINFO),NULL,NULL,NULL,0,0,640,400,0,0,0,0,0,0,NULL};
PROCESS_INFORMATION pinfo;
int ret = CreateProcess(
program,args,NULL,NULL,FALSE,DETACHED_PROCESS,NULL,NULL,&info,&pinfo);
if(!ret){
printf("CreateProcess failed.");
return -1;
}
printf("success");
WaitForSingleObject(pinfo.hProcess,INFINITE);
CloseHandle(pinfo.hThread);
CloseHandle(pinfo.hProcess);
}
実行結果
こんな感じ。(Process Hackerの出力)
parent: create_process.exeは親プロセスのこの記事で言う、「実行する側」のexe
Windows標準のタスクマネージャではこんな感じ
見たまま、Hello worldってダイアログがポコっと出るだけ。
けど、tmpファイルがそのまま実行されていることがわかる。
適当にコンパイルして実行してみると、へーってなる。
多分挙動的に、NTFS ADSにあるファイルにも適用できそう。
おわり。