実行ファイルのリソースを取得する方法

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
フェルナンデス

実行ファイルのリソースを取得する方法

#1

投稿記事 by フェルナンデス » 10年前

FindResource(hHandle,リソース名,リソースタイプ);
ここのリソース名は何が入るのですか?

ID_VERSION_DIALOG DIALOG 0,0,230,90
STYLE DS_3DLOOK | DS_CENTER | DS_MODALFRAME | DS_SHELLFONT | WS_CAPTION | WS_VISIBLE | WS_POPUP | WS_SYSMENU
CAPTION "バージョン"
FONT 9, "Ms Shell Dlg"
BEGIN
CONTROL "",IDC_SUNKEN ,"STATIC" ,SS_LEFT | SS_SUNKEN ,5 ,50 ,220 ,1
END

こんな感じのダイアログリソースだったらID_VERSION_DIALOGがリソース名ですか?

もしそうだとすれば、私が作ったアプリであれば、リソースファイル内を見ればわかりますが、
人様が作成したアプリのリソースを実行ファイルから見たいとすると、リソース名がわからないと思うのですが、
これはどうすればいいのでしょうか?

リソースの情報をすべて取得したいのです。

よろしくお願いします。

YuO
記事: 947
登録日時: 14年前
住所: 東京都世田谷区

Re: 実行ファイルのリソースを取得する方法

#2

投稿記事 by YuO » 10年前

フェルナンデス さんが書きました:FindResource(hHandle,リソース名,リソースタイプ);
ここのリソース名は何が入るのですか?
リソースに.rcファイル等でつけた名前です。
フェルナンデス さんが書きました:こんな感じのダイアログリソースだったらID_VERSION_DIALOGがリソース名ですか?
YesでありNoです。
おそらく,ID_VERSION_DIALOGは#defineされた整数値だと思います。
この場合,リソース名はその整数値,または#とそれに続く10進数で表された値であって,ID_VERSION_DIALOGではありません。
通常,MAKEINTRESOURCE マクロで整数型から文字列型に変換します。
フェルナンデス さんが書きました:もしそうだとすれば、私が作ったアプリであれば、リソースファイル内を見ればわかりますが、
人様が作成したアプリのリソースを実行ファイルから見たいとすると、リソース名がわからないと思うのですが、
これはどうすればいいのでしょうか?
リソースの情報をすべて取得したいのです。
FindResource FunctionをMSDNでひけば,左側の階層構造でFindResourceが書いてある上に,列挙系のAPIが見つかります。
これらを使えばリソースの取得が可能です。

というか……。と,MSDNにそのものずばりの情報があるのですが……。

フェルナンデス

Re: 実行ファイルのリソースを取得する方法

#3

投稿記事 by フェルナンデス » 10年前

ありがとうございます。
順番的には
Module = LoadLibrary(FileName); //実行ファイルのモジュールハンドルを取得
EnumResourceTypes(Module,(ENUMRESTYPEPROC)EnumResTypeProc,0);//リソースタイプを取得
EnumResourceNames(Module,リソースタイプ,(ENUMRESNAMEPROC)EnumResNameProc,0);//リソース名を取得(上記でタイプが複数ある場合はループさせる)
FindResource(Module,リソース名,リソースタイプ);//リソース名とリソースタイプが複数ある場合はループさせる
こんな感じでいいのでしょうか?

最終的にやりたいことは、メニューやダイアログ内、その他アプリケーション内で描画されている文字列(メニューであれば「ファイル」など)をすべて取得し、配列に収めたいのですが、
可能でしょうか?

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: 実行ファイルのリソースを取得する方法

#4

投稿記事 by みけCAT » 10年前

フェルナンデス さんが書きました:最終的にやりたいことは、メニューやダイアログ内、その他アプリケーション内で描画されている文字列(メニューであれば「ファイル」など)をすべて取得し、配列に収めたいのですが、
可能でしょうか?
不可能ではないかもしれませんが、かなり難しい気がします。
そもそも、アプリケーション内で描画されている文字列が、全てリソースに含まれるとは限りません。
ウィンドウに関連付けられたテキスト(ここではスタティックテキストやボタン、エディットボックスなどで通常使われる文字列のこと)なら、
対象のウィンドウの子ウィンドウを列挙し、テキストを取得できるかもしれません。
しかし、そうでない、例えばGDIやDXライブラリのDrawStringなどで描画されたテキストの取得は難しいと思います。
例えば、プログラムを解析しながら実行(インタプリタ的な感じ?)して、描画命令に渡される文字列を取得するか、
画像を解析して文字画像を文字に変換する(OCR)などの方法が考えられます。
また、例えばNNScanTextでは
このモードでは、テキストを取得したい画面を再描画させて、その描画内容(テキスト)を取得しています。
(http://web.archive.org/web/201205040227 ... NNScanText)
という手法を用いており、手元のWindows Vistaで試したところ、
GDI描画ではテキストは取得出来ましたが、対象のアプリケーションがデータ実行防止で死にました。
また、DXライブラリで描画されたテキストは取得できませんでした。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

フェルナンデス

Re: 実行ファイルのリソースを取得する方法

#5

投稿記事 by フェルナンデス » 10年前

みけCAT さんが書きました:
フェルナンデス さんが書きました:最終的にやりたいことは、メニューやダイアログ内、その他アプリケーション内で描画されている文字列(メニューであれば「ファイル」など)をすべて取得し、配列に収めたいのですが、
可能でしょうか?
不可能ではないかもしれませんが、かなり難しい気がします。
そもそも、アプリケーション内で描画されている文字列が、全てリソースに含まれるとは限りません。
ウィンドウに関連付けられたテキスト(ここではスタティックテキストやボタン、エディットボックスなどで通常使われる文字列のこと)なら、
対象のウィンドウの子ウィンドウを列挙し、テキストを取得できるかもしれません。
しかし、そうでない、例えばGDIやDXライブラリのDrawStringなどで描画されたテキストの取得は難しいと思います。
例えば、プログラムを解析しながら実行(インタプリタ的な感じ?)して、描画命令に渡される文字列を取得するか、
画像を解析して文字画像を文字に変換する(OCR)などの方法が考えられます。
また、例えばNNScanTextでは
このモードでは、テキストを取得したい画面を再描画させて、その描画内容(テキスト)を取得しています。
(http://web.archive.org/web/201205040227 ... NNScanText)
という手法を用いており、手元のWindows Vistaで試したところ、
GDI描画ではテキストは取得出来ましたが、対象のアプリケーションがデータ実行防止で死にました。
また、DXライブラリで描画されたテキストは取得できませんでした。[/quote

すみません。言い方が悪かったです。
リソースで書かれている文字列を取得したいのです。
スタティックテキストやボタン、エディットボックスなどで通常使われる文字列は無視していいです。
あくまでリソース内の文字列のみです。

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: 実行ファイルのリソースを取得する方法

#6

投稿記事 by みけCAT » 10年前

フェルナンデス さんが書きました:ありがとうございます。
順番的には
Module = LoadLibrary(FileName); //実行ファイルのモジュールハンドルを取得
EnumResourceTypes(Module,(ENUMRESTYPEPROC)EnumResTypeProc,0);//リソースタイプを取得
EnumResourceNames(Module,リソースタイプ,(ENUMRESNAMEPROC)EnumResNameProc,0);//リソース名を取得(上記でタイプが複数ある場合はループさせる)
FindResource(Module,リソース名,リソースタイプ);//リソース名とリソースタイプが複数ある場合はループさせる
こんな感じでいいのでしょうか?
とりあえず実装し、実行してみることはしましたか?
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: 実行ファイルのリソースを取得する方法

#7

投稿記事 by みけCAT » 10年前

答え合わせにどうぞ。
Resource HackerTM
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

フェルナンデス

Re: 実行ファイルのリソースを取得する方法

#8

投稿記事 by フェルナンデス » 10年前

みけCAT さんが書きました:
フェルナンデス さんが書きました:ありがとうございます。
順番的には
Module = LoadLibrary(FileName); //実行ファイルのモジュールハンドルを取得
EnumResourceTypes(Module,(ENUMRESTYPEPROC)EnumResTypeProc,0);//リソースタイプを取得
EnumResourceNames(Module,リソースタイプ,(ENUMRESNAMEPROC)EnumResNameProc,0);//リソース名を取得(上記でタイプが複数ある場合はループさせる)
FindResource(Module,リソース名,リソースタイプ);//リソース名とリソースタイプが複数ある場合はループさせる
こんな感じでいいのでしょうか?
とりあえず実装し、実行してみることはしましたか?
はい。しました。

Module = LoadLibrary(FileName);
EnumResourceTypes(Module,(ENUMRESTYPEPROC)EnumResTypeProc,0);

BOOL CALLBACK EnumResTypeProc(HMODULE hModule,LPTSTR lpType,LONG_PTR lParam)
{
EnumResourceNames(hModule,lpType,(ENUMRESNAMEPROC)NamesCallback,0);
return TRUE;
}

BOOL CALLBACK NamesCallback(HMODULE hModule,LPCTSTR lpType,LPTSTR lpName,LONG lParam)
{
HRSRC hHandle;
DWORD rSize;
const void *rData;
char *buffer;

hHandle = FindResource(hModule,lpName,lpType);
rSize = SizeofResource(hModule,hHandle);
rData = LockResource(LoadResource(hModule,hHandle));

buffer = (char *)malloc(rSize+1);
memcpy(buffer,rData,rSize);

buffer[rSize] = '\0';

MessageBox(NULL,buffer,"てst",MB_OK);
return TRUE;
}


この段階でメッセージボックスに表示される内容が意味不明で行き詰っています。

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: 実行ファイルのリソースを取得する方法

#9

投稿記事 by みけCAT » 10年前

コードを提示するときはBBcodeを有効にした状態でcodeタグで囲み、
かつ適切なインデントをしていただけると、見やすくて助かります。

おそらく仕様です。
リソースの内容を取得するには、そのタイプに応じて適切な関数を使う必要があるようです。
そもそも、LoadResource関数を呼んでいないようですが、LockResource関数でエラーは出ていないでしょうか?
FindResource function (Windows) さんが書きました:An application can use FindResource to find any type of resource, but this function should be used only if the application must access the binary resource data by making subsequent calls to LoadResource and then to LockResource.
FindResource function (Windows)
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

フェルナンデス

Re: 実行ファイルのリソースを取得する方法

#10

投稿記事 by フェルナンデス » 10年前

みけCAT さんが書きました:コードを提示するときはBBcodeを有効にした状態でcodeタグで囲み、
かつ適切なインデントをしていただけると、見やすくて助かります。

おそらく仕様です。
リソースの内容を取得するには、そのタイプに応じて適切な関数を使う必要があるようです。
そもそも、LoadResource関数を呼んでいないようですが、LockResource関数でエラーは出ていないでしょうか?
FindResource function (Windows) さんが書きました:An application can use FindResource to find any type of resource, but this function should be used only if the application must access the binary resource data by making subsequent calls to LoadResource and then to LockResource.
FindResource function (Windows)
LockResource(LoadResource(hModule,hHandle));
この部分で使用しています。

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: 実行ファイルのリソースを取得する方法

#11

投稿記事 by みけCAT » 10年前

フェルナンデス さんが書きました:
みけCAT さんが書きました:コードを提示するときはBBcodeを有効にした状態でcodeタグで囲み、
かつ適切なインデントをしていただけると、見やすくて助かります。

おそらく仕様です。
リソースの内容を取得するには、そのタイプに応じて適切な関数を使う必要があるようです。
そもそも、LoadResource関数を呼んでいないようですが、LockResource関数でエラーは出ていないでしょうか?
FindResource function (Windows) さんが書きました:An application can use FindResource to find any type of resource, but this function should be used only if the application must access the binary resource data by making subsequent calls to LoadResource and then to LockResource.
FindResource function (Windows)
LockResource(LoadResource(hModule,hHandle));
この部分で使用しています。
失礼しました。

また、この程度のデータ量では問題にはならなそうですが、mallocで確保した領域をfreeで開放していないのが気になりました。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: 実行ファイルのリソースを取得する方法

#12

投稿記事 by みけCAT » 10年前

こちらでリソースをダンプするプログラムを書いて見てみました。
一部のタイプに関してはは文字コードが「それっぽい」かをチェックすることで
Unicodeで書かれた文字列を抜き出すことも可能かもしれないですが、
やはりそれぞれのタイプ用の読み込み関数を利用したほうが良さそうです。

コード:

#include <cstdio>
#include <string>
#include <vector>
#include <windows.h>

struct restype_t {
	std::string res_type;
	LPTSTR raw_type;
	bool type_is_int;

	restype_t(){}
	restype_t(const std::string& type, LPTSTR rtype): res_type(type), raw_type(rtype),
		type_is_int(((unsigned long)rtype & 0xFFFF0000) == 0) {}
};

struct resource_t {
	std::string res_type;
	std::string res_name;
	LPCTSTR raw_type;
	LPTSTR raw_name;
	bool type_is_int, name_is_int;

	resource_t(){}
	resource_t(const std::string& type, const std::string& name, LPCTSTR rtype, LPTSTR rname):
		res_type(type), res_name(name), raw_type(rtype), raw_name(rname),
		type_is_int(((unsigned long)rtype & 0xFFFF0000) == 0),
		name_is_int(((unsigned long)rname & 0xFFFF0000) == 0) {}
};

BOOL CALLBACK EnumResTypeProc(HMODULE, LPTSTR lpszType, LONG_PTR lParam) {
	if (((unsigned long)lpszType & 0xFFFF0000) != 0) {
		// ポインタ
		((std::vector<restype_t>*)lParam)->push_back(restype_t(std::string(lpszType), lpszType));
	} else {
		// MAKEINTRESOURCEの疑い
		char buffer[1024] ={};
		sprintf(buffer, "MAKEINTRESOURCE(%d)", (int)lpszType);
		((std::vector<restype_t>*)lParam)->push_back(restype_t(std::string(buffer), lpszType));
	}
	return TRUE;
}

BOOL CALLBACK EnumResNameProc(HMODULE, LPCTSTR lpszType, LPTSTR lpszName, LONG_PTR lParam) {
	std::string res_type, res_name;
	if (((unsigned long)lpszType & 0xFFFF0000) != 0) {
		// ポインタ
		res_type = std::string(lpszType);
	} else {
		// MAKEINTRESOURCEの疑い
		char buffer[1024] ={};
		sprintf(buffer, "MAKEINTRESOURCE(%d)", (int)lpszType);
		res_type = std::string(buffer);
	}
	if (((unsigned long)lpszName & 0xFFFF0000) != 0) {
		// ポインタ
		res_name = std::string(lpszName);
	} else {
		// MAKEINTRESOURCEの疑い
		char buffer[1024] ={};
		sprintf(buffer, "MAKEINTRESOURCE(%d)", (int)lpszName);
		res_name = std::string(buffer);
	}
	((std::vector<resource_t>*)lParam)->push_back(resource_t(res_type, res_name, lpszType, lpszName));
	return TRUE;
}

int main(int argc, char *argv[]) {
	if (argc != 2) {
		fprintf(stderr, "Usage: %s <file name>\n", argc >= 1 ? argv[0] : "enum_res");
		return 1;
	}

	std::vector<restype_t> res_types;
	std::vector<resource_t> resources;
	HMODULE hModule;
	hModule = LoadLibrary(argv[1]);
	if (hModule == NULL) {
		char buffer[1024] = {};
		FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), LANG_USER_DEFAULT,
			buffer, sizeof(buffer), NULL);
		fprintf(stderr, "LoadLibrary error : %s\n", buffer);
		return 1;
	}
	EnumResourceTypes(hModule, EnumResTypeProc, (LONG_PTR)&res_types);
	for (unsigned int i = 0; i < res_types.size(); i++) {
		printf("resource type: %s\n", res_types[i].res_type.c_str());
		EnumResourceNames(hModule,
			res_types[i].type_is_int ? res_types[i].raw_type : res_types[i].res_type.c_str(),
			EnumResNameProc, (LONG_PTR)&resources);
	}
	puts("\nenumerated resources:");
	for (unsigned int i = 0; i < resources.size(); i++) {
		printf("%s\t%s\n", resources[i].res_type.c_str(), resources[i].res_name.c_str());
		HRSRC hResInfo = FindResource(hModule,
			resources[i].name_is_int ? resources[i].raw_name : resources[i].res_name.c_str(),
			resources[i].type_is_int ? resources[i].raw_type : resources[i].res_type.c_str()
		);
		HGLOBAL hRes = LoadResource(hModule, hResInfo);
		DWORD res_size = SizeofResource(hModule, hResInfo);
		LPVOID pRes = LockResource(hRes);

		char file_name[1024] = {};
		sprintf(file_name, "dump\\%s__%s.dat", resources[i].res_type.c_str(), resources[i].res_name.c_str());
		FILE* fp = fopen(file_name, "wb");
		if (fp != NULL) {
			fwrite(pRes, 1, res_size, fp);
			fclose(fp);
		}
	}
	FreeLibrary(hModule);
	return 0;
}
※カレントディレクトリに空のdumpディレクトリを用意してから実行してください。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

フェルナンデス

Re: 実行ファイルのリソースを取得する方法

#13

投稿記事 by フェルナンデス » 10年前

返信が遅くなり申し訳ありません。
参考ソースありがとうございます。

前の
>そもそも、アプリケーション内で描画されている文字列が、全てリソースに含まれるとは限りません。
>ウィンドウに関連付けられたテキスト(ここではスタティックテキストやボタン、エディットボックスなどで通常使われる文字列のこと)なら、
>対象のウィンドウの子ウィンドウを列挙し、テキストを取得できるかもしれません。
>しかし、そうでない、例えばGDIやDXライブラリのDrawStringなどで描画されたテキストの取得は難しいと思います。
この回答を見直して改めてひとつ思ったことがあるのですが、
実行ファイルをバイナリエディタにかけて表示されるバイナリデータというのは
リソースや、ウィンドウに関連付けられたテキストが含まれたバイナリですよね?
GDIやDXライブラリのDrawStringなどで描画されたテキストの取得は難しいとのことなので、可能な範囲でそれらの文字列をバイナリデータから
抽出することは可能なのでしょうか?

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: 実行ファイルのリソースを取得する方法

#14

投稿記事 by みけCAT » 10年前

フェルナンデス さんが書きました:実行ファイルをバイナリエディタにかけて表示されるバイナリデータというのは
リソースや、ウィンドウに関連付けられたテキストが含まれたバイナリですよね?
GDIやDXライブラリのDrawStringなどで描画されたテキストの取得は難しいとのことなので、可能な範囲でそれらの文字列をバイナリデータから
抽出することは可能なのでしょうか?
ある程度可能だと思います。
方法は、バイナリデータのうちShift_JISやUnicode(UTF-16LE)として解釈できる部分を探して抽出します。
ある程度長い文字列のみ抽出するようにしないと、おそらく1~数文字のノイズが大量に抽出されるでしょう。
難読化や動的生成などにより生成され、そもそもバイナリデータに含まれていない文字列はこの方法では抽出できません。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

フェルナンデス

Re: 実行ファイルのリソースを取得する方法

#15

投稿記事 by フェルナンデス » 10年前

みけCAT さんが書きました:
フェルナンデス さんが書きました:実行ファイルをバイナリエディタにかけて表示されるバイナリデータというのは
リソースや、ウィンドウに関連付けられたテキストが含まれたバイナリですよね?
GDIやDXライブラリのDrawStringなどで描画されたテキストの取得は難しいとのことなので、可能な範囲でそれらの文字列をバイナリデータから
抽出することは可能なのでしょうか?
ある程度可能だと思います。
方法は、バイナリデータのうちShift_JISやUnicode(UTF-16LE)として解釈できる部分を探して抽出します。
ある程度長い文字列のみ抽出するようにしないと、おそらく1~数文字のノイズが大量に抽出されるでしょう。
難読化や動的生成などにより生成され、そもそもバイナリデータに含まれていない文字列はこの方法では抽出できません。
抽出したいのが英文、英単語なのですが、その場合はUTF-8ということでよろしいですか?

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: 実行ファイルのリソースを取得する方法

#16

投稿記事 by みけCAT » 10年前

フェルナンデス さんが書きました:
みけCAT さんが書きました:
フェルナンデス さんが書きました:実行ファイルをバイナリエディタにかけて表示されるバイナリデータというのは
リソースや、ウィンドウに関連付けられたテキストが含まれたバイナリですよね?
GDIやDXライブラリのDrawStringなどで描画されたテキストの取得は難しいとのことなので、可能な範囲でそれらの文字列をバイナリデータから
抽出することは可能なのでしょうか?
ある程度可能だと思います。
方法は、バイナリデータのうちShift_JISやUnicode(UTF-16LE)として解釈できる部分を探して抽出します。
ある程度長い文字列のみ抽出するようにしないと、おそらく1~数文字のノイズが大量に抽出されるでしょう。
難読化や動的生成などにより生成され、そもそもバイナリデータに含まれていない文字列はこの方法では抽出できません。
抽出したいのが英文、英単語なのですが、その場合はUTF-8ということでよろしいですか?
GTKを用いたプログラムであれば、UTF-8だろうと思います。
普通のWindowsアプリケーションの場合は、Shift_JISまたはUnicode(UTF-16LE)を用いることが多いと思います。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

フェルナンデス

Re: 実行ファイルのリソースを取得する方法

#17

投稿記事 by フェルナンデス » 10年前

みけCAT さんが書きました: GTKを用いたプログラムであれば、UTF-8だろうと思います。
普通のWindowsアプリケーションの場合は、Shift_JISまたはUnicode(UTF-16LE)を用いることが多いと思います。
海外ソフトでもShift_JISまたはUnicode(UTF-16LE)なのでしょうか?
たとえば、プログラマさんが使いそうでわかりそうなソフトで言うと、IDA Proや、OLLYDBGなどの英文・英単語の描画文字です。

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: 実行ファイルのリソースを取得する方法

#18

投稿記事 by みけCAT » 10年前

フェルナンデス さんが書きました:海外ソフトでもShift_JISまたはUnicode(UTF-16LE)なのでしょうか?
たとえば、プログラマさんが使いそうでわかりそうなソフトで言うと、IDA Proや、OLLYDBGなどの英文・英単語の描画文字です。
OllyDbg v2.01ではShift_JISとUnicode(UTF-16LE)が混在していました。
といっても、半角英数字はShift_JISでもUTF-8でもEUCでも同じコードになると思います。
英文のみを抽出する場合は、漢字などを除外できるので、効率よく文字列を抽出できるかもしれません。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

フェルナンデス

Re: 実行ファイルのリソースを取得する方法

#19

投稿記事 by フェルナンデス » 10年前

みけCAT さんが書きました:
フェルナンデス さんが書きました:海外ソフトでもShift_JISまたはUnicode(UTF-16LE)なのでしょうか?
たとえば、プログラマさんが使いそうでわかりそうなソフトで言うと、IDA Proや、OLLYDBGなどの英文・英単語の描画文字です。
OllyDbg v2.01ではShift_JISとUnicode(UTF-16LE)が混在していました。
といっても、半角英数字はShift_JISでもUTF-8でもEUCでも同じコードになると思います。
英文のみを抽出する場合は、漢字などを除外できるので、効率よく文字列を抽出できるかもしれません。
そうですか。
では、実行順序は
バイナリ取得→文字コード変換→英数字抽出
という感じになりますね?
文字コードの変換部分は関数を自作するしかないのですか?

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: 実行ファイルのリソースを取得する方法

#20

投稿記事 by みけCAT » 10年前

フェルナンデス さんが書きました:では、実行順序は
バイナリ取得→文字コード変換→英数字抽出
という感じになりますね?
文字コードの変換部分は関数を自作するしかないのですか?
「バイナリ取得」というのがよくわからないですが、読み込みのことですか?
英数字(文字列)を抽出してから文字コード変換の方がいいかもしれません。
そもそも、英数字だけならまともな文字コード変換は必要ないかもしれません。

コマンドライン引数で与えられたファイルから5文字以上のASCII文字列(Shift_JIS or UTF-16LE)を抽出し、
標準出力に出力するプログラムを書いてみました。

コード:

#include <stdio.h>

/* 出力する文字列の最低の長さ */
#define MIN_COMBO 5

int main(int argc,char* argv[]) {
	char buffer[MIN_COMBO];
	char prev_char='\0';
	int combo_count=0;
	int zero_count=0;
	int unicode_mode=0;
	int input;
	int i;
	FILE* fp;
	if(argc!=2) {
		fprintf(stderr,"Usage: %s input_file\n", argc>0?argv[0]:"eibun_chusyutu");
		return 1;
	}
	fp=fopen(argv[1],"rb");
	if(fp==NULL) {
		fprintf(stderr,"failed to open %s\n",argv[1]);
		return 1;
	}
	while((input=getc(fp))!=EOF) {
		if(0x20<=input && input<=0x7e) {
			/* ASCII文字 */
			if(combo_count==0 || !unicode_mode) {
				/* 文字列の最初 or Shift_JIS文字列 */
				unicode_mode=0;
				if(combo_count>=MIN_COMBO) {
					/* 設定数以上連続していれば出力 */
					putchar(input);
				} else {
					/* バッファに格納する */
					buffer[combo_count++]=input;
					if(combo_count>=MIN_COMBO) {
						for(i=0;i<MIN_COMBO;i++)putchar(buffer[i]);
					}
				}
			}
			zero_count=0;
		} else if(input==0x00) {
			/* NUL文字 */
			zero_count++;
			if(zero_count==1) {
				if(0x20<=prev_char && prev_char<=0x7e) {
					if(combo_count==0 || combo_count==1 || unicode_mode) {
						/* 文字列の最初 or Unicode文字列 */
						if(!unicode_mode && combo_count==1)combo_count=0;
						unicode_mode=1;
						if(combo_count>=MIN_COMBO) {
							/* 設定数以上連続していれば出力 */
							putchar(prev_char);
						} else {
							/* バッファに格納する */
							buffer[combo_count++]=prev_char;
							if(combo_count>=MIN_COMBO) {
								for(i=0;i<MIN_COMBO;i++)putchar(buffer[i]);
							}
						}
					} else {
						/* 文字列の終わり */
						if(combo_count>=MIN_COMBO)putchar('\n');
						combo_count=0;
						unicode_mode=0;
					}
				} else {
					combo_count=0;
					unicode_mode=0;
				}
			} else if(zero_count==2) {
				if(!unicode_mode) {
					combo_count=0;
					unicode_mode=0;
				}
			} else if(zero_count==3) {
				if(unicode_mode && combo_count>=MIN_COMBO) {
					/* 文字列の終わり */
					if(combo_count>=MIN_COMBO)putchar('\n');
					combo_count=0;
					unicode_mode=0;
				}
			} else {
				combo_count=0;
				unicode_mode=0;
			}
		} else {
			unicode_mode=0;
			zero_count=0;
			combo_count=0;
		}
		prev_char=input;
	}
	fclose(fp);
	return 0;
}
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

閉鎖

“C言語何でも質問掲示板” へ戻る