HSPポータル
サイトマップ お問い合わせ


HSPTV!掲示板


未解決 解決 停止 削除要請

2015
0303
catsADS(代替データストリーム)を取得5解決


cats

リンク

2015/3/3(Tue) 21:06:47|NO.67661

まず、代替データストリームとは、Windows NTから採用されたNTFSの、フォーク機能です。
例えば、hello.txtに対して、

echo hello > hello.txt:hoge
というコマンドを実行することでhello.txtのhogeというADSに"hello"というデータが書き込まれます。
本来この機能により作成されたファイルは見えませんが、

dir /r >hello.txt:hoge:$DATA
のように見ることができます。

さて、HSPでこの代替データストリームのファイル名を取得し、またファイルの内容も取得したいと考えております。
調べたところ、Windows Vista以降はFindFirstFileとFindNextFileを使ってADSを含むデータを取得できるとありました。
そこでFindNextFileを使ってファイルの一覧を取得したのですが、ADSが検出されません。
ADSの内容の取得は

bload "file_name:ads_name:$DATA", buf
により可能でした。
つまり、ADSの名前(上のads_name)の部分さえ取得できればよいのですが、FindNextFileでは検出できないのでしょうか。
以下に今回書いた、ADS以外のファイル一覧を取得するコードを載せます。

#uselib "kernel32.dll" #cfunc FindFirstFile "FindFirstFileW" str, int #cfunc FindNextFile "FindNextFileW" int, int #func FindClose "FindClose" int // 変数初期化 sdim lpFileName, 512 ; lpFileName sdim lpFindFileData, 512 ; lpFindFileData sdim cFileName, 512 ; ファイル名(WIN32_FIND_DATA) hFile = 0 ; ファイルハンドル // ファイル一覧取得 chdir "C:\\" ; 探索対象ディレクトリ lpFileName = "*" ; 全てのファイル cnvstow lpFileName, lpFileName ; Unicodeに対応 hFile = FindFirstFile( lpFileName, varptr(lpFindFileData) ) if ( hFile == -1 ) : mes "Directory Not Found." : stop while FindNextFile( hFile, varptr(lpFindFileData) ) // lpFindFileDataのバイナリを見る限り0x2CからUnicodeでファイル名? memcpy cFileName, lpFindFileData, 64, 0, 0x2C cFileName = cnvwtos(cFileName) mes cFileName wend FindClose hFile stop
NTFSなので、ファイルを指す文字列は全てUnicodeにしています。
厄介なプログラムですが、どなたかご教示お願いします。



この記事に返信する


totori

リンク

2015/3/3(Tue) 21:21:37|NO.67662

http://www.codeproject.com/Articles/13667/Enumerating-Alternate-Data-Streams
を見ると、

... 略) FindFirstStreamW() and FindNextStreamW().
This set of functions is quite similar to the FindFirstFile type of APIs.

FindFirstFileによく似た関数を使うとあるので実際に使うのは、
FindFirstStreamW() と FindNextStreamW()ではないでしょうか?



cats

リンク

2015/3/3(Tue) 22:24:13|NO.67663

> totori 様
ご指摘ありがとうございます。確かにFindFirstStreamWと間違えていました。
すぐに修正したのですが、ディレクトリを指定してもハンドルが取得できないようになってしまいました。

#uselib "kernel32.dll" #cfunc FindFirstStream "FindFirstStreamW" str, int, int, int #cfunc FindNextStream "FindNextStreamW" int, int #func FindClose "FindClose" int #cfunc GetLastError "GetLastError" // 変数初期化 sdim lpFileName, 512 ; lpFileName sdim lpFindFileData, 512 ; lpFindFileData sdim cFileName, 512 ; ファイル名(WIN32_FIND_DATA) hFile = 0 ; ファイルハンドル // ファイル一覧取得 lpFileName = "C:\\" ; ディレクトリ指定 cnvstow lpFileName, lpFileName ; Unicodeに対応 hFile = FindFirstStream( lpFileName, 1/*FindStreamInfoMaxInfoLevel*/, varptr(lpFindFileData), 0 ) eNum = GetLastError() //***** エラー番号87 => パラメータが間違っています。 *****// if ( hFile == -1 ) : mes "Directory Not Found." : stop while FindNextStream( hFile, varptr(lpFindFileData) ) memcpy cFileName, lpFindFileData, 64, 0, 0x2C cFileName = cnvwtos(cFileName) mes cFileName wend FindClose hFile stop
GetLastErrorで確認したところ、「パラメータが間違っています」とのことです。
引き続き試行しようと思いますが、コードに間違いがありましたらご指摘の方をお願いします。



totori

リンク

2015/3/3(Tue) 22:52:41|NO.67664

こんな感じ?


#uselib "kernel32.dll" #cfunc FindFirstStream "FindFirstStreamW" wstr, int, int, int #cfunc FindNextStream "FindNextStreamW" int, int #func FindClose "FindClose" int #cfunc GetLastError "GetLastError" #define ERROR_HANDLE_EOF 0x00000026 // 変数初期化 sdim lpFileName, 512 ; lpFileName sdim lpFindStreamData, (260+36)*2 + 8 ; lpFindStreamData sdim cFileName, (260+36)*2 ; ファイル名(WIN32_FIND_STREAM_DATA) hFile = 0 ; ファイルハンドル // ファイル一覧取得 lpFileName = "C:\\" ; ディレクトリ指定 ;cnvstow lpFileName, lpFileName ; Unicodeに対応 hFile = FindFirstStream( lpFileName, 0/*FindStreamInfoStandard*/, varptr(lpFindStreamData), 0 ) eNum = GetLastError() //***** エラー番号87 => パラメータが間違っています。 *****// if ( hFile == -1 ) : mes "Directory Not Found." : stop while FindNextStream( hFile, varptr(lpFindStreamData) ) memcpy cFileName, lpFindStreamData, (260+36)*2, 0, 8 cFileName = cnvwtos(cFileName) mes cFileName wend FindClose hFile stop



cats

リンク

2015/3/3(Tue) 23:29:59|NO.67666

> totori 様
細かい修正までありがとうございます。
コードを実行したところエラー番号が変わっていたのでいくつか試したところ、(少なくとも私の環境では)ファイルを指定したときのみ正常に動作しました。
てっきりディレクトリも指定できるのかと思っていました。
それから、Unicodeは関数の引数にwstrを取ればよかったのですね。今後W系でstring型を使うときは注意します。
とりあえず、ファイルの一覧を取得して1つずつ検知することができました。

#uselib "kernel32.dll" #cfunc FindFirstFile "FindFirstFileW" wstr, int #cfunc FindNextFile "FindNextFileW" int, int #cfunc FindFirstStream "FindFirstStreamW" wstr, int, int, int #cfunc FindNextStream "FindNextStreamW" int, int #func FindClose "FindClose" int // 変数初期化 sdim lpFileName, 512 ; lpFileName sdim s_lpFileName, 512 ; lpFileName sdim lpFindFileData, (260+36)*2 + 8 ; lpFindFileData sdim cFileName, (260+36)*2 ; ファイル名(WIN32_FIND_DATA) sdim s_lpFindStreamData, (260+36)*2 + 8 ; lpFindStreamData sdim s_cFileName, (260+36)*2 ; ファイル名(WIN32_FIND_STREAM_DATA) hFile = 0 ; ハンドル(ディレクトリ) s_hFile = 0 ; ハンドル(ファイル) // ファイル一覧取得 s_lpFileName = "C:\\hoge\\" chdir s_lpFileName lpFileName = "*" ; ディレクトリ指定 hFile = FindFirstFile( lpFileName, varptr(lpFindFileData) ) if ( hFile == -1 ) : mes "Directory Not Found." : stop while FindNextFile( hFile, varptr(lpFindFileData) ) memcpy cFileName, lpFindFileData, 64, 0, 0x2C cFileName = cnvwtos(cFileName) mes s_lpFileName + cFileName s_hFile = FindFirstStream( s_lpFileName + cFileName, 0, varptr(s_lpFindStreamData), 0 ) if ( s_hFile == -1 ) { mes "Stream Not Found." } else { while FindNextStream( s_hFile, varptr(s_lpFindStreamData) ) memcpy s_cFileName, s_lpFindStreamData, (260+36)*2, 0, 8 s_cFileName = cnvwtos(s_cFileName) mes s_cFileName wend } wend FindClose hFile stop
結果

C:\hoge\.. Stream Not Found. C:\hoge\stream.jpg :flag:$DATA
無事ADSの検出ができました。totori様、ありがとうございました。



cats

リンク

2015/3/3(Tue) 23:30:13|NO.67667

解決



ONION software Copyright 1997-2021(c) All rights reserved.