diff options
Diffstat (limited to 'tools')
109 files changed, 352 insertions, 18247 deletions
diff --git a/tools/SCsub b/tools/SCsub index f046e9ad08..5613d8a6c9 100644 --- a/tools/SCsub +++ b/tools/SCsub @@ -11,7 +11,6 @@ if (env["tools"]!="no"): SConscript('collada/SCsub'); SConscript('docdump/SCsub'); SConscript('freetype/SCsub'); - SConscript('pe_bliss/SCsub'); SConscript('doc/SCsub') SConscript('pck/SCsub') diff --git a/tools/editor/animation_editor.cpp b/tools/editor/animation_editor.cpp index cdce910665..dfb09e38fc 100644 --- a/tools/editor/animation_editor.cpp +++ b/tools/editor/animation_editor.cpp @@ -35,6 +35,7 @@ #include "scene/gui/separator.h" #include "editor_node.h" #include "tools/editor/plugins/animation_player_editor_plugin.h" +#include "scene/main/viewport.h" /* Missing to fix: *Set @@ -256,6 +257,28 @@ public: //PopupDialog *ke_dialog; + void _fix_node_path(Variant &value) { + + + NodePath np=value; + + if (np==NodePath()) + return; + + Node* root = EditorNode::get_singleton()->get_tree()->get_root(); + + Node* np_node = root->get_node(np); + ERR_FAIL_COND(!np_node); + + Node* edited_node = root->get_node(base); + ERR_FAIL_COND(!edited_node); + + + + value = edited_node->get_path_to(np_node); + } + + void _update_obj(const Ref<Animation> &p_anim) { if (setting) return; @@ -356,10 +379,18 @@ public: case Animation::TYPE_VALUE: { if (name=="value") { + + Variant value = p_value; + + if (value.get_type()==Variant::NODE_PATH) { + + _fix_node_path(value); + } + setting=true; undo_redo->create_action("Anim Change Value",true); Variant prev = animation->track_get_key_value(track,key); - undo_redo->add_do_method(animation.ptr(),"track_set_key_value",track,key,p_value); + undo_redo->add_do_method(animation.ptr(),"track_set_key_value",track,key,value); undo_redo->add_undo_method(animation.ptr(),"track_set_key_value",track,key,prev); undo_redo->add_do_method(this,"_update_obj",animation); undo_redo->add_undo_method(this,"_update_obj",animation); @@ -420,7 +451,14 @@ public: } if (what=="value") { - args[idx]=p_value; + + Variant value=p_value; + if (value.get_type()==Variant::NODE_PATH) { + + _fix_node_path(value); + } + + args[idx]=value; d_new["args"]=args; mergeable=true; } @@ -441,7 +479,7 @@ public: } break; } - return false; + return false; @@ -616,6 +654,7 @@ public: float key_ofs; PropertyInfo hint; + NodePath base; void notify_change() { @@ -1630,8 +1669,9 @@ void AnimationKeyEditor::_select_at_anim(const Ref<Animation>& p_anim,int p_trac } -PropertyInfo AnimationKeyEditor::_find_hint_for_track(int p_idx) { +PropertyInfo AnimationKeyEditor::_find_hint_for_track(int p_idx,NodePath& r_base_path) { + r_base_path=NodePath(); ERR_FAIL_COND_V(!animation.is_valid(),PropertyInfo()); ERR_FAIL_INDEX_V(p_idx,animation->get_track_count(),PropertyInfo()); @@ -1640,9 +1680,6 @@ PropertyInfo AnimationKeyEditor::_find_hint_for_track(int p_idx) { NodePath path = animation->track_get_path(p_idx); - String property = path.get_property(); - if (property=="") - return PropertyInfo(); if (!root->has_node_and_resource(path)) return PropertyInfo(); @@ -1650,6 +1687,15 @@ PropertyInfo AnimationKeyEditor::_find_hint_for_track(int p_idx) { RES res; Node *node = root->get_node_and_resource(path,res); + + if (node) { + r_base_path=node->get_path(); + } + + String property = path.get_property(); + if (property=="") + return PropertyInfo(); + List<PropertyInfo> pinfo; if (res.is_valid()) res->get_property_list(&pinfo); @@ -1729,7 +1775,7 @@ bool AnimationKeyEditor::_edit_if_single_selection() { key_edit->animation=animation; key_edit->track=idx; key_edit->key_ofs=animation->track_get_key_time(idx,key); - key_edit->hint=_find_hint_for_track(idx); + key_edit->hint=_find_hint_for_track(idx,key_edit->base); key_edit->notify_change(); curve_edit->set_transition(animation->track_get_key_transition(idx,key)); @@ -2187,7 +2233,8 @@ void AnimationKeyEditor::_track_editor_input_event(const InputEvent& p_input) { newval=d; } else if (tt==Animation::TYPE_VALUE) { - PropertyInfo inf = _find_hint_for_track(idx); + NodePath np; + PropertyInfo inf = _find_hint_for_track(idx,np); if (inf.type!=Variant::NIL) { Variant::CallError err; @@ -2975,6 +3022,7 @@ void AnimationKeyEditor::_clear_selection() { key_edit->track=0; key_edit->key_ofs=0; key_edit->hint=PropertyInfo(); + key_edit->base=NodePath(); key_edit->notify_change(); } @@ -3022,9 +3070,14 @@ Node *AnimationKeyEditor::get_root() const { -void AnimationKeyEditor::set_keying(bool p_enabled) { +void AnimationKeyEditor::update_keying() { - keying=p_enabled; + bool keying_enabled=is_visible() && animation.is_valid(); + + if (keying_enabled==keying) + return; + + keying=keying_enabled; _update_menu(); emit_signal("keying_changed"); @@ -3032,7 +3085,7 @@ void AnimationKeyEditor::set_keying(bool p_enabled) { bool AnimationKeyEditor::has_keying() const { - return is_visible() && animation.is_valid(); + return keying; } void AnimationKeyEditor::_query_insert(const InsertData& p_id) { @@ -3264,9 +3317,10 @@ int AnimationKeyEditor::_confirm_insert(InsertData p_id,int p_last_track) { { //shitty hack + NodePath np; animation->add_track(p_id.type); animation->track_set_path(animation->get_track_count()-1,p_id.path); - PropertyInfo h = _find_hint_for_track(animation->get_track_count()-1); + PropertyInfo h = _find_hint_for_track(animation->get_track_count()-1,np); animation->remove_track(animation->get_track_count()-1); //hack @@ -3640,6 +3694,9 @@ void AnimationKeyEditor::_add_call_track(const NodePath& p_base) { NodePath path = root->get_path_to(from); + //print_line("root: "+String(root->get_path())); + //print_line("path: "+String(path)); + undo_redo->create_action("Anim Add Call Track"); undo_redo->add_do_method(animation.ptr(),"add_track",Animation::TYPE_METHOD); undo_redo->add_do_method(animation.ptr(),"track_set_path",animation->get_track_count(),path); diff --git a/tools/editor/animation_editor.h b/tools/editor/animation_editor.h index c8a539179e..cd22dc3106 100644 --- a/tools/editor/animation_editor.h +++ b/tools/editor/animation_editor.h @@ -302,7 +302,7 @@ class AnimationKeyEditor : public VBoxContainer { void _select_at_anim(const Ref<Animation>& p_anim,int p_track,float p_pos); void _curve_transition_changed(float p_what); - PropertyInfo _find_hint_for_track(int p_idx); + PropertyInfo _find_hint_for_track(int p_idx, NodePath &r_base_path); void _create_value_item(int p_type); void _pane_drag(const Point2& p_delta); @@ -324,7 +324,7 @@ public: Ref<Animation> get_current_animation() const; void set_root(Node *p_root); Node *get_root() const; - void set_keying(bool p_enabled); + void update_keying(); bool has_keying() const; void cleanup(); diff --git a/tools/editor/editor_file_system.cpp b/tools/editor/editor_file_system.cpp index c7c1a48e34..ad59efc46f 100644 --- a/tools/editor/editor_file_system.cpp +++ b/tools/editor/editor_file_system.cpp @@ -1166,8 +1166,10 @@ EditorFileSystemDirectory *EditorFileSystem::get_path(const String& p_path) { void EditorFileSystem::_resource_saved(const String& p_path){ + //print_line("resource saved: "+p_path); EditorFileSystem::get_singleton()->update_file(p_path); + } String EditorFileSystem::_find_first_from_source(EditorFileSystemDirectory* p_dir,const String &p_src) const { diff --git a/tools/editor/editor_import_export.cpp b/tools/editor/editor_import_export.cpp index 77331256f3..b845eba66b 100644 --- a/tools/editor/editor_import_export.cpp +++ b/tools/editor/editor_import_export.cpp @@ -162,6 +162,7 @@ EditorExportPlugin::EditorExportPlugin() { ///////////////////////////////////////////////////////////////////////////////////////////////////// + static void _add_to_list(EditorFileSystemDirectory *p_efsd,Set<StringName>& r_list) { for(int i=0;i<p_efsd->get_subdir_count();i++) { @@ -170,13 +171,11 @@ static void _add_to_list(EditorFileSystemDirectory *p_efsd,Set<StringName>& r_li } for(int i=0;i<p_efsd->get_file_count();i++) { - r_list.insert(p_efsd->get_file_path(i)); } } - struct __EESortDepCmp { _FORCE_INLINE_ bool operator()(const StringName& p_l,const StringName& p_r) const { @@ -187,7 +186,7 @@ struct __EESortDepCmp { -static void _add_files_with_filter(DirAccess *da,const List<String>& p_filters,Set<StringName>& r_list) { +static void _edit_files_with_filter(DirAccess *da,const List<String>& p_filters,Set<StringName>& r_list,bool exclude) { List<String> files; @@ -218,8 +217,17 @@ static void _add_files_with_filter(DirAccess *da,const List<String>& p_filters,S for(const List<String>::Element *F=p_filters.front();F;F=F->next()) { if (fullpath.matchn(F->get())) { - r_list.insert(fullpath); - print_line("Added: "+fullpath); + String act = "Added: "; + + if (!exclude) { + r_list.insert(fullpath); + } else { + act = "Removed: "; + r_list.erase(fullpath); + } + + + print_line(act+fullpath); } } } @@ -230,13 +238,13 @@ static void _add_files_with_filter(DirAccess *da,const List<String>& p_filters,S if (E->get().begins_with(".")) continue; da->change_dir(E->get()); - _add_files_with_filter(da,p_filters,r_list); + _edit_files_with_filter(da,p_filters,r_list,exclude); da->change_dir(".."); } } -static void _add_filter_to_list(Set<StringName>& r_list,const String& p_filter) { +static void _edit_filter_list(Set<StringName>& r_list,const String& p_filter,bool exclude) { if (p_filter=="") return; @@ -250,11 +258,16 @@ static void _add_filter_to_list(Set<StringName>& r_list,const String& p_filter) } DirAccess *da = DirAccess::open("res://"); - _add_files_with_filter(da,filters,r_list); + _edit_files_with_filter(da,filters,r_list,exclude); memdelete(da); +} +static void _add_filter_to_list(Set<StringName>& r_list,const String& p_filter) { + _edit_filter_list(r_list,p_filter,false); +} - +static void _remove_filter_from_list(Set<StringName>& r_list,const String& p_filter) { + _edit_filter_list(r_list,p_filter,true); } Vector<uint8_t> EditorExportPlatform::get_exported_file_default(String& p_fname) const { @@ -307,6 +320,8 @@ Vector<StringName> EditorExportPlatform::get_dependencies(bool p_bundles) const cf+="*.flags"; _add_filter_to_list(exported,cf); + cf = EditorImportExport::get_singleton()->get_export_custom_filter_exclude(); + _remove_filter_from_list(exported,cf); } @@ -380,6 +395,9 @@ Vector<StringName> EditorExportPlatform::get_dependencies(bool p_bundles) const cf+="*.flags"; _add_filter_to_list(exported,cf); + cf = EditorImportExport::get_singleton()->get_export_custom_filter_exclude(); + _remove_filter_from_list(exported,cf); + } @@ -1530,13 +1548,17 @@ EditorImportExport::ExportFilter EditorImportExport::get_export_filter() const{ } void EditorImportExport::set_export_custom_filter(const String& p_custom_filter){ - export_custom_filter=p_custom_filter; } +void EditorImportExport::set_export_custom_filter_exclude(const String& p_custom_filter){ + export_custom_filter_exclude=p_custom_filter; +} String EditorImportExport::get_export_custom_filter() const{ - return export_custom_filter; } +String EditorImportExport::get_export_custom_filter_exclude() const{ + return export_custom_filter_exclude; +} void EditorImportExport::set_export_image_action(ImageAction p_action) { @@ -1699,6 +1721,7 @@ void EditorImportExport::load_config() { export_custom_filter=cf->get_value("export_filter","filter"); + export_custom_filter_exclude=cf->get_value("export_filter","filter_exclude"); String t=cf->get_value("export_filter","type"); if (t=="selected") export_filter=EXPORT_SELECTED; @@ -1888,6 +1911,7 @@ void EditorImportExport::save_config() { } cf->set_value("export_filter","filter",export_custom_filter); + cf->set_value("export_filter", "filter_exclude",export_custom_filter_exclude); String file_action_section = "export_filter_files"; diff --git a/tools/editor/editor_import_export.h b/tools/editor/editor_import_export.h index 272464d9b0..60b7f919d8 100644 --- a/tools/editor/editor_import_export.h +++ b/tools/editor/editor_import_export.h @@ -285,7 +285,7 @@ protected: Set<String> image_formats; ExportFilter export_filter; - String export_custom_filter; + String export_custom_filter, export_custom_filter_exclude; Map<StringName,FileAction> files; Map<StringName,Ref<EditorExportPlatform> > exporters; Map<StringName,ImageGroup> image_groups; @@ -332,7 +332,9 @@ public: ExportFilter get_export_filter() const; void set_export_custom_filter(const String& p_custom_filter); + void set_export_custom_filter_exclude(const String& p_custom_filter); String get_export_custom_filter() const; + String get_export_custom_filter_exclude() const; void set_export_image_action(ImageAction p_action); ImageAction get_export_image_action() const; diff --git a/tools/editor/editor_node.cpp b/tools/editor/editor_node.cpp index 9fe76a738a..b270d8b8cc 100644 --- a/tools/editor/editor_node.cpp +++ b/tools/editor/editor_node.cpp @@ -2214,7 +2214,7 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) { case FILE_EXPORT_PROJECT: { - project_export_settings->popup_centered_ratio(); + project_export_settings->popup_export(); /* String target = export_db->get_current_platform(); Ref<EditorExporter> exporter = export_db->get_exporter(target); @@ -3661,6 +3661,7 @@ void EditorNode::update_keying() { property_editor->set_keying(valid); + AnimationPlayerEditor::singleton->get_key_editor()->update_keying(); } @@ -4592,6 +4593,16 @@ ToolButton *EditorNode::add_bottom_panel_item(String p_text,Control *p_item) { } +bool EditorNode::are_bottom_panels_hidden() const { + + for(int i=0;i<bottom_panel_items.size();i++) { + if (bottom_panel_items[i].button->is_pressed()) + return false; + } + + return true; +} + void EditorNode::hide_bottom_panel() { _bottom_panel_switch(false,0); @@ -5030,10 +5041,14 @@ EditorNode::EditorNode() { srt->add_child(scene_tabs); - scene_root_parent = memnew( Panel ); + scene_root_parent = memnew( PanelContainer ); + scene_root_parent->set_custom_minimum_size(Size2(0,80)); + + + //Ref<StyleBox> sp = scene_root_parent->get_stylebox("panel","TabContainer"); + //scene_root_parent->add_style_override("panel",sp); + - Ref<StyleBox> sp = scene_root_parent->get_stylebox("panel","TabContainer"); - scene_root_parent->add_style_override("panel",sp); /*scene_root_parent->set_anchor( MARGIN_RIGHT, Control::ANCHOR_END ); scene_root_parent->set_anchor( MARGIN_BOTTOM, Control::ANCHOR_END ); scene_root_parent->set_begin( Point2( 0, 0) ); @@ -5041,13 +5056,6 @@ EditorNode::EditorNode() { srt->add_child(scene_root_parent); scene_root_parent->set_v_size_flags(Control::SIZE_EXPAND_FILL); - scene_root_base = memnew( Control ); - scene_root_base->set_area_as_parent_rect(); - for(int i=0;i<4;i++) { - scene_root_base->set_margin(Margin(i),sp->get_margin(Margin(i))); - } - scene_root_parent->add_child(scene_root_base); - scene_root = memnew( Viewport ); @@ -5062,11 +5070,11 @@ EditorNode::EditorNode() { // scene_root->set_world_2d( Ref<World2D>( memnew( World2D )) ); - viewport = memnew( Control ); - viewport->set_area_as_parent_rect(4); - for(int i=0;i<4;i++) { + viewport = memnew( VBoxContainer ); + viewport->set_v_size_flags(Control::SIZE_EXPAND_FILL); + /*for(int i=0;i<4;i++) { viewport->set_margin(Margin(i),sp->get_margin(Margin(i))); - } + }*/ scene_root_parent->add_child(viewport); diff --git a/tools/editor/editor_node.h b/tools/editor/editor_node.h index 4dc942c023..a8aa6ac1f4 100644 --- a/tools/editor/editor_node.h +++ b/tools/editor/editor_node.h @@ -258,7 +258,7 @@ class EditorNode : public Node { TextEdit *load_errors; AcceptDialog *load_error_dialog; - Control *scene_root_base; + //Control *scene_root_base; Ref<Theme> theme; PopupMenu *recent_scenes; @@ -670,6 +670,7 @@ public: ToolButton* add_bottom_panel_item(String p_text,Control *p_item); + bool are_bottom_panels_hidden() const; void make_bottom_panel_item_visible(Control *p_item); void raise_bottom_panel_item(Control *p_item); void hide_bottom_panel(); diff --git a/tools/editor/groups_editor.cpp b/tools/editor/groups_editor.cpp index 6840a8b205..4b1096148a 100644 --- a/tools/editor/groups_editor.cpp +++ b/tools/editor/groups_editor.cpp @@ -51,6 +51,8 @@ void GroupsEditor::_add_group(const String& p_group) { undo_redo->add_undo_method(this,"update_tree"); undo_redo->commit_action(); + + group_name->clear(); } void GroupsEditor::_remove_group(Object *p_item, int p_column, int p_id) { diff --git a/tools/editor/icons/icon_reload_empty.png b/tools/editor/icons/icon_reload_empty.png Binary files differnew file mode 100644 index 0000000000..d43582b2c4 --- /dev/null +++ b/tools/editor/icons/icon_reload_empty.png diff --git a/tools/editor/icons/icon_reload_small.png b/tools/editor/icons/icon_reload_small.png Binary files differnew file mode 100644 index 0000000000..957cdfcf4f --- /dev/null +++ b/tools/editor/icons/icon_reload_small.png diff --git a/tools/editor/plugins/animation_player_editor_plugin.cpp b/tools/editor/plugins/animation_player_editor_plugin.cpp index 43b4276d45..32afd86970 100644 --- a/tools/editor/plugins/animation_player_editor_plugin.cpp +++ b/tools/editor/plugins/animation_player_editor_plugin.cpp @@ -128,16 +128,9 @@ void AnimationPlayerEditor::_notification(int p_what) { anim_editor_load->set_hover_texture( get_icon("AnimGetHl","EditorIcons")); anim_editor_store->set_hover_texture( get_icon("AnimSetHl","EditorIcons")); */ - } - - if (p_what==NOTIFICATION_READY) { get_tree()->connect("node_removed",this,"_node_removed"); } - - if (p_what==NOTIFICATION_DRAW) { - - } } void AnimationPlayerEditor::_autoplay_pressed() { @@ -1305,7 +1298,7 @@ AnimationPlayerEditor::AnimationPlayerEditor(EditorNode *p_editor) { frame = memnew( SpinBox ); hb->add_child(frame); - frame->set_custom_minimum_size(Size2(80,0)); + frame->set_custom_minimum_size(Size2(60,0)); frame->set_stretch_ratio(2); frame->set_tooltip("Animation position (in seconds)."); diff --git a/tools/editor/plugins/canvas_item_editor_plugin.cpp b/tools/editor/plugins/canvas_item_editor_plugin.cpp index a259fa0fcc..ef2df539e8 100644 --- a/tools/editor/plugins/canvas_item_editor_plugin.cpp +++ b/tools/editor/plugins/canvas_item_editor_plugin.cpp @@ -603,6 +603,9 @@ bool CanvasItemEditor::_select(CanvasItem *item, Point2 p_click_pos, bool p_appe CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>(); if (!canvas_item || !canvas_item->is_visible()) continue; + if (canvas_item->get_viewport()!=EditorNode::get_singleton()->get_scene_root()) + continue; + CanvasItemEditorSelectedItem *se=editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item); if (!se) continue; @@ -643,6 +646,9 @@ void CanvasItemEditor::_key_move(const Vector2& p_dir, bool p_snap, KeyMoveMODE CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>(); if (!canvas_item || !canvas_item->is_visible()) continue; + if (canvas_item->get_viewport()!=EditorNode::get_singleton()->get_scene_root()) + continue; + CanvasItemEditorSelectedItem *se=editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item); if (!se) continue; @@ -702,6 +708,9 @@ Point2 CanvasItemEditor::_find_topleftmost_point() { CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>(); if (!canvas_item || !canvas_item->is_visible()) continue; + if (canvas_item->get_viewport()!=EditorNode::get_singleton()->get_scene_root()) + continue; + @@ -731,6 +740,9 @@ int CanvasItemEditor::get_item_count() { if (!canvas_item || !canvas_item->is_visible()) continue; + if (canvas_item->get_viewport()!=EditorNode::get_singleton()->get_scene_root()) + continue; + ic++; }; @@ -749,6 +761,8 @@ CanvasItem *CanvasItemEditor::get_single_item() { CanvasItem *canvas_item = E->key()->cast_to<CanvasItem>(); if (!canvas_item || !canvas_item->is_visible()) continue; + if (canvas_item->get_viewport()!=EditorNode::get_singleton()->get_scene_root()) + continue; if (single_item) return NULL; //morethan one @@ -1102,6 +1116,9 @@ void CanvasItemEditor::_viewport_input_event(const InputEvent& p_event) { CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>(); if (!canvas_item || !canvas_item->is_visible()) continue; + if (canvas_item->get_viewport()!=EditorNode::get_singleton()->get_scene_root()) + continue; + CanvasItemEditorSelectedItem *se=editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item); if (!se) @@ -1194,6 +1211,9 @@ void CanvasItemEditor::_viewport_input_event(const InputEvent& p_event) { CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>(); if (!canvas_item || !canvas_item->is_visible()) continue; + if (canvas_item->get_viewport()!=EditorNode::get_singleton()->get_scene_root()) + continue; + CanvasItemEditorSelectedItem *se=editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item); if (!se) continue; @@ -1400,6 +1420,9 @@ void CanvasItemEditor::_viewport_input_event(const InputEvent& p_event) { CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>(); if (!canvas_item || !canvas_item->is_visible()) continue; + if (canvas_item->get_viewport()!=EditorNode::get_singleton()->get_scene_root()) + continue; + CanvasItemEditorSelectedItem *se=editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item); if (!se) continue; @@ -1507,6 +1530,9 @@ void CanvasItemEditor::_viewport_input_event(const InputEvent& p_event) { CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>(); if (!canvas_item || !canvas_item->is_visible()) continue; + if (canvas_item->get_viewport()!=EditorNode::get_singleton()->get_scene_root()) + continue; + CanvasItemEditorSelectedItem *se=editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item); if (!se) continue; @@ -1881,6 +1907,8 @@ void CanvasItemEditor::_viewport_draw() { CanvasItem *canvas_item = E->key()->cast_to<CanvasItem>(); if (!canvas_item || !canvas_item->is_visible()) continue; + if (canvas_item->get_viewport()!=EditorNode::get_singleton()->get_scene_root()) + continue; CanvasItemEditorSelectedItem *se=editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item); if (!se) continue; @@ -2104,6 +2132,9 @@ void CanvasItemEditor::_notification(int p_what) { if (!canvas_item || !canvas_item->is_visible()) continue; + if (canvas_item->get_viewport()!=EditorNode::get_singleton()->get_scene_root()) + continue; + if (canvas_item->cast_to<Control>()) has_control=true; else @@ -2509,6 +2540,9 @@ void CanvasItemEditor::_popup_callback(int p_op) { if (!canvas_item || !canvas_item->is_visible()) continue; + if (canvas_item->get_viewport()!=EditorNode::get_singleton()->get_scene_root()) + continue; + canvas_item->set_meta("_edit_lock_",true); emit_signal("item_lock_status_changed"); } @@ -2524,6 +2558,9 @@ void CanvasItemEditor::_popup_callback(int p_op) { if (!canvas_item || !canvas_item->is_visible()) continue; + if (canvas_item->get_viewport()!=EditorNode::get_singleton()->get_scene_root()) + continue; + canvas_item->set_meta("_edit_lock_",Variant()); emit_signal("item_lock_status_changed"); @@ -2542,6 +2579,9 @@ void CanvasItemEditor::_popup_callback(int p_op) { if (!canvas_item || !canvas_item->is_visible()) continue; + if (canvas_item->get_viewport()!=EditorNode::get_singleton()->get_scene_root()) + continue; + canvas_item->set_meta("_edit_group_",true); emit_signal("item_group_status_changed"); } @@ -2557,6 +2597,9 @@ void CanvasItemEditor::_popup_callback(int p_op) { if (!canvas_item || !canvas_item->is_visible()) continue; + if (canvas_item->get_viewport()!=EditorNode::get_singleton()->get_scene_root()) + continue; + canvas_item->set_meta("_edit_group_",Variant()); emit_signal("item_group_status_changed"); } @@ -2575,6 +2618,9 @@ void CanvasItemEditor::_popup_callback(int p_op) { if (!canvas_item || !canvas_item->is_visible()) continue; + if (canvas_item->get_viewport()!=EditorNode::get_singleton()->get_scene_root()) + continue; + Control *c = canvas_item->cast_to<Control>(); if (!c) @@ -2693,6 +2739,9 @@ void CanvasItemEditor::_popup_callback(int p_op) { if (!canvas_item || !canvas_item->is_visible()) continue; + if (canvas_item->get_viewport()!=EditorNode::get_singleton()->get_scene_root()) + continue; + if (canvas_item->cast_to<Node2D>()) { Node2D *n2d = canvas_item->cast_to<Node2D>(); @@ -2803,6 +2852,8 @@ void CanvasItemEditor::_popup_callback(int p_op) { if (!canvas_item || !canvas_item->is_visible()) continue; + if (canvas_item->get_viewport()!=EditorNode::get_singleton()->get_scene_root()) + continue; if (canvas_item->cast_to<Node2D>()) { @@ -2853,6 +2904,9 @@ void CanvasItemEditor::_popup_callback(int p_op) { if (!canvas_item || !canvas_item->is_visible()) continue; + if (canvas_item->get_viewport()!=EditorNode::get_singleton()->get_scene_root()) + continue; + if (canvas_item->cast_to<Node2D>()) { Node2D *n2d = canvas_item->cast_to<Node2D>(); @@ -2887,6 +2941,9 @@ void CanvasItemEditor::_popup_callback(int p_op) { for(Map<Node*,Object*>::Element *E=selection.front();E;E=E->next()) { CanvasItem *canvas_item = E->key()->cast_to<CanvasItem>(); if (!canvas_item) continue; + if (canvas_item->get_viewport()!=EditorNode::get_singleton()->get_scene_root()) + continue; + // counting invisible items, for now //if (!canvas_item->is_visible()) continue; @@ -2979,6 +3036,8 @@ void CanvasItemEditor::_popup_callback(int p_op) { if (!canvas_item || !canvas_item->is_visible()) continue; + if (canvas_item->get_viewport()!=EditorNode::get_singleton()->get_scene_root()) + continue; canvas_item->set_meta("_edit_ik_",true); @@ -3469,6 +3528,7 @@ CanvasItemEditorPlugin::CanvasItemEditorPlugin(EditorNode *p_node) { editor=p_node; canvas_item_editor = memnew( CanvasItemEditor(editor) ); + canvas_item_editor->set_v_size_flags(Control::SIZE_EXPAND_FILL); editor->get_viewport()->add_child(canvas_item_editor); canvas_item_editor->set_area_as_parent_rect(); canvas_item_editor->hide(); diff --git a/tools/editor/plugins/script_editor_plugin.cpp b/tools/editor/plugins/script_editor_plugin.cpp index 34d7e89760..bef74ebcfe 100644 --- a/tools/editor/plugins/script_editor_plugin.cpp +++ b/tools/editor/plugins/script_editor_plugin.cpp @@ -935,6 +935,9 @@ void ScriptEditor::_menu_option(int p_option) { if (!_test_script_times_on_disk()) return; + save_all_scripts(); + +#if 0 for(int i=0;i<tab_container->get_child_count();i++) { ScriptTextEditor *ste = tab_container->get_child(i)->cast_to<ScriptTextEditor>(); @@ -951,7 +954,7 @@ void ScriptEditor::_menu_option(int p_option) { editor->save_resource( script ); } - +#endif } break; case SEARCH_HELP: { @@ -1694,7 +1697,7 @@ void ScriptEditor::ensure_select_current() { Ref<Script> script = ste->get_edited_script(); - if (!grab_focus_block && is_inside_tree()) + if (!grab_focus_block && is_visible()) ste->get_text_edit()->grab_focus(); edit_menu->show(); @@ -1938,9 +1941,7 @@ void ScriptEditor::edit(const Ref<Script>& p_script) { } } -void ScriptEditor::save_external_data() { - - apply_scripts(); +void ScriptEditor::save_all_scripts() { for(int i=0;i<tab_container->get_child_count();i++) { @@ -1949,9 +1950,13 @@ void ScriptEditor::save_external_data() { if (!ste) continue; + if (ste->get_text_edit()->get_version()==ste->get_text_edit()->get_saved_version()) + continue; + Ref<Script> script = ste->get_edited_script(); if (script->get_path()!="" && script->get_path().find("local://")==-1 &&script->get_path().find("::")==-1) { //external script, save it + ste->apply_code(); editor->save_resource(script); //ResourceSaver::save(script->get_path(),script); } @@ -2063,7 +2068,7 @@ void ScriptEditor::_editor_settings_changed() { void ScriptEditor::_autosave_scripts() { print_line("autosaving"); - save_external_data(); + save_all_scripts(); } void ScriptEditor::_tree_changed() { @@ -2628,7 +2633,7 @@ void ScriptEditorPlugin::clear() { void ScriptEditorPlugin::save_external_data() { - script_editor->save_external_data(); + script_editor->save_all_scripts(); } void ScriptEditorPlugin::apply_changes() { @@ -2672,7 +2677,7 @@ ScriptEditorPlugin::ScriptEditorPlugin(EditorNode *p_node) { editor=p_node; script_editor = memnew( ScriptEditor(p_node) ); editor->get_viewport()->add_child(script_editor); - script_editor->set_area_as_parent_rect(); + script_editor->set_v_size_flags(Control::SIZE_EXPAND_FILL); script_editor->hide(); diff --git a/tools/editor/plugins/script_editor_plugin.h b/tools/editor/plugins/script_editor_plugin.h index c52da41a43..5664b26580 100644 --- a/tools/editor/plugins/script_editor_plugin.h +++ b/tools/editor/plugins/script_editor_plugin.h @@ -295,7 +295,7 @@ public: void swap_lines(TextEdit *tx, int line1, int line2); - void save_external_data(); + void save_all_scripts(); void set_window_layout(Ref<ConfigFile> p_layout); void get_window_layout(Ref<ConfigFile> p_layout); diff --git a/tools/editor/plugins/spatial_editor_plugin.cpp b/tools/editor/plugins/spatial_editor_plugin.cpp index 236d69dfb3..cf92473919 100644 --- a/tools/editor/plugins/spatial_editor_plugin.cpp +++ b/tools/editor/plugins/spatial_editor_plugin.cpp @@ -4217,8 +4217,10 @@ SpatialEditorPlugin::SpatialEditorPlugin(EditorNode *p_node) { editor=p_node; spatial_editor = memnew( SpatialEditor(p_node) ); + spatial_editor->set_v_size_flags(Control::SIZE_EXPAND_FILL); editor->get_viewport()->add_child(spatial_editor); - spatial_editor->set_area_as_parent_rect(); + + //spatial_editor->set_area_as_parent_rect(); spatial_editor->hide(); spatial_editor->connect("transform_key_request",editor,"_transform_keyed"); diff --git a/tools/editor/plugins/tile_map_editor_plugin.cpp b/tools/editor/plugins/tile_map_editor_plugin.cpp index 29326a2222..acacd37f66 100644 --- a/tools/editor/plugins/tile_map_editor_plugin.cpp +++ b/tools/editor/plugins/tile_map_editor_plugin.cpp @@ -533,6 +533,8 @@ void TileMapEditor::_canvas_draw() { if (node->get_half_offset()!=TileMap::HALF_OFFSET_X) { + int max_lines=2000; //avoid crash if size too smal + for(int i=(si.pos.x)-1;i<=(si.pos.x+si.size.x);i++) { Vector2 from = xform.xform(node->map_to_world(Vector2(i,si.pos.y))); @@ -540,10 +542,12 @@ void TileMapEditor::_canvas_draw() { Color col=i==0?Color(1,0.8,0.2,0.5):Color(1,0.3,0.1,0.2); canvas_item_editor->draw_line(from,to,col,1); - + if (max_lines--==0) + break; } } else { + int max_lines=10000; //avoid crash if size too smal for(int i=(si.pos.x)-1;i<=(si.pos.x+si.size.x);i++) { @@ -558,11 +562,17 @@ void TileMapEditor::_canvas_draw() { Vector2 to = xform.xform(node->map_to_world(Vector2(i,j+1),true)+ofs); Color col=i==0?Color(1,0.8,0.2,0.5):Color(1,0.3,0.1,0.2); canvas_item_editor->draw_line(from,to,col,1); + + if (max_lines--==0) + break; + } } } + int max_lines=10000; //avoid crash if size too smal + if (node->get_half_offset()!=TileMap::HALF_OFFSET_Y) { for(int i=(si.pos.y)-1;i<=(si.pos.y+si.size.y);i++) { @@ -573,6 +583,9 @@ void TileMapEditor::_canvas_draw() { Color col=i==0?Color(1,0.8,0.2,0.5):Color(1,0.3,0.1,0.2); canvas_item_editor->draw_line(from,to,col,1); + if (max_lines--==0) + break; + } } else { @@ -590,6 +603,10 @@ void TileMapEditor::_canvas_draw() { Vector2 to = xform.xform(node->map_to_world(Vector2(j+1,i),true)+ofs); Color col=i==0?Color(1,0.8,0.2,0.5):Color(1,0.3,0.1,0.2); canvas_item_editor->draw_line(from,to,col,1); + + if (max_lines--==0) + break; + } } diff --git a/tools/editor/project_export.cpp b/tools/editor/project_export.cpp index 7690d31e7b..b5e7715d93 100644 --- a/tools/editor/project_export.cpp +++ b/tools/editor/project_export.cpp @@ -122,6 +122,15 @@ void ProjectExportDialog::_tree_changed() { } +void ProjectExportDialog::popup_export() { + popup_centered_ratio(); + if (pending_update_tree) { + _update_tree(); + _update_group_tree(); + pending_update_tree=false; + } +} + void ProjectExportDialog::_update_tree() { @@ -168,6 +177,11 @@ void ProjectExportDialog::_scan_finished() { print_line("**********SCAN DONEEE********"); print_line("**********SCAN DONEEE********");*/ + if (!is_visible()) { + pending_update_tree=true; + return; + } + _update_tree(); _update_group_tree(); } @@ -203,6 +217,11 @@ void ProjectExportDialog::_filters_edited(String what) { _save_export_cfg(); } +void ProjectExportDialog::_filters_exclude_edited(String what) { + EditorImportExport::get_singleton()->set_export_custom_filter_exclude(what); + _save_export_cfg(); +} + void ProjectExportDialog::_quality_edited(float what) { EditorImportExport::get_singleton()->set_export_image_quality(what); @@ -300,6 +319,7 @@ void ProjectExportDialog::_notification(int p_what) { export_mode->select( EditorImportExport::get_singleton()->get_export_filter() ); convert_text_scenes->set_pressed( EditorImportExport::get_singleton()->get_convert_text_scenes() ); filters->set_text( EditorImportExport::get_singleton()->get_export_custom_filter() ); + filters_exclude->set_text( EditorImportExport::get_singleton()->get_export_custom_filter_exclude() ); if (EditorImportExport::get_singleton()->get_export_filter()!=EditorImportExport::EXPORT_SELECTED) tree_vb->hide(); else @@ -1069,6 +1089,7 @@ void ProjectExportDialog::_bind_methods() { ObjectTypeDB::bind_method(_MD("_prop_edited"),&ProjectExportDialog::_prop_edited); ObjectTypeDB::bind_method(_MD("_export_mode_changed"),&ProjectExportDialog::_export_mode_changed); ObjectTypeDB::bind_method(_MD("_filters_edited"),&ProjectExportDialog::_filters_edited); + ObjectTypeDB::bind_method(_MD("_filters_exclude_edited"),&ProjectExportDialog::_filters_exclude_edited); ObjectTypeDB::bind_method(_MD("_export_action"),&ProjectExportDialog::_export_action); ObjectTypeDB::bind_method(_MD("_export_action_pck"),&ProjectExportDialog::_export_action_pck); ObjectTypeDB::bind_method(_MD("_quality_edited"),&ProjectExportDialog::_quality_edited); @@ -1181,8 +1202,11 @@ ProjectExportDialog::ProjectExportDialog(EditorNode *p_editor) { tree->set_column_min_width(1,90); filters = memnew( LineEdit ); - vb->add_margin_child("Filters to export non-resource files (Comma Separated, ie: *.json, *.txt):",filters); + vb->add_margin_child("Filters to export non-resource files (Comma Separated, eg: *.json, *.txt):",filters); filters->connect("text_changed",this,"_filters_edited"); + filters_exclude = memnew( LineEdit ); + vb->add_margin_child("Filters to exclude from export (Comma Separated, eg: *.json, *.txt):",filters_exclude); + filters_exclude->connect("text_changed",this,"_filters_exclude_edited"); convert_text_scenes = memnew( CheckButton ); convert_text_scenes->set_text("Convert text scenes to binary on export"); @@ -1446,7 +1470,7 @@ ProjectExportDialog::ProjectExportDialog(EditorNode *p_editor) { ei="EditorIcons"; ot="Object"; - + pending_update_tree=true; } @@ -1480,6 +1504,8 @@ void ProjectExport::popup_export() { popup_centered(Size2(300,100)); + + } Error ProjectExport::export_project(const String& p_preset) { @@ -1880,5 +1906,6 @@ ProjectExport::ProjectExport(EditorData* p_data) { error = memnew( AcceptDialog ); add_child(error); + } diff --git a/tools/editor/project_export.h b/tools/editor/project_export.h index 5a42a58e58..dc076ce201 100644 --- a/tools/editor/project_export.h +++ b/tools/editor/project_export.h @@ -70,11 +70,12 @@ private: TabContainer *sections; bool updating_tree; + bool pending_update_tree; AcceptDialog *error; ConfirmationDialog *confirm; Button *button_reload; - LineEdit *filters; + LineEdit *filters, *filters_exclude; HBoxContainer *plat_errors; Label *platform_error_string; @@ -154,6 +155,7 @@ private: void _platform_selected(); void _filters_edited(String what); + void _filters_exclude_edited(String what); void _update_group_tree(); void _image_filter_changed(String); @@ -203,6 +205,7 @@ public: Error export_platform(const String& p_platform, const String& p_path, bool p_debug,const String& p_password,bool p_quit_after=false); + void popup_export(); ProjectExportDialog(EditorNode *p_editor); ~ProjectExportDialog(); }; diff --git a/tools/editor/project_settings.cpp b/tools/editor/project_settings.cpp index 6c5e18ec9a..873e397010 100644 --- a/tools/editor/project_settings.cpp +++ b/tools/editor/project_settings.cpp @@ -38,18 +38,18 @@ ProjectSettings *ProjectSettings::singleton=NULL; static const char* _button_names[JOY_BUTTON_MAX]={ -"PS X, XBox A, NDS B", -"PS Circle, XBox B, NDS A", -"PS Square, XBox X, NDS Y", -"PS Triangle, XBox Y, NDS X", -"L, L1, Wii C", +"PS X, XBox A, Nintendo B", +"PS Circle, XBox B, Nintendo A", +"PS Square, XBox X, Nintendo Y", +"PS Triangle, XBox Y, Nintendo X", +"L, L1", "R, R1", -"L2, Wii Z", +"L2", "R2", "L3", "R3", -"Select, Wii -", -"Start, Wii +", +"Select, Nintendo -", +"Start, Nintendo +", "D-Pad Up", "D-Pad Down", "D-Pad Left", @@ -299,10 +299,22 @@ void ProjectSettings::_add_item(int p_item){ device_id->set_val(0); device_index_label->set_text("Joy Button Axis:"); device_index->clear(); - for(int i=0;i<24;i++) { + for(int i=0;i<JOY_AXIS_MAX*2;i++) { + String desc; - device_index->add_item("Axis "+itos(i/2)+" "+(i&1?"+":"-")); + int ax=i/2; + if (ax==0 || ax==1) + desc=" (Left Stick)"; + else if (ax==2 || ax==3) + desc=" (Right Stick)"; + else if (ax==6) + desc=" (L2)"; + else if (ax==7) + desc=" (R2)"; + + + device_index->add_item("Axis "+itos(i/2)+" "+(i&1?"+":"-")+desc); } device_input->popup_centered(Size2(350,95)); @@ -315,7 +327,7 @@ void ProjectSettings::_add_item(int p_item){ for(int i=0;i<JOY_BUTTON_MAX;i++) { - device_index->add_item(String(_button_names[i])); + device_index->add_item(itos(i)+": "+String(_button_names[i])); } device_input->popup_centered(Size2(350,95)); @@ -474,7 +486,7 @@ void ProjectSettings::_update_actions() { case InputEvent::JOYSTICK_BUTTON: { String str = "Device "+itos(ie.device)+", Button "+itos(ie.joy_button.button_index); - if (ie.joy_button.button_index>=0 && ie.joy_button.button_index<14) + if (ie.joy_button.button_index>=0 && ie.joy_button.button_index<JOY_BUTTON_MAX) str+=String()+" ("+_button_names[ie.joy_button.button_index]+")."; else str+="."; @@ -499,7 +511,18 @@ void ProjectSettings::_update_actions() { } break; case InputEvent::JOYSTICK_MOTION: { - String str = "Device "+itos(ie.device)+", Axis "+itos(ie.joy_motion.axis)+" "+(ie.joy_motion.axis_value<0?"-.":"+."); + String desc; + int ax = ie.joy_motion.axis; + + if (ax==0 || ax==1) + desc=" (Left Stick)."; + else if (ax==2 || ax==3) + desc=" (Right Stick)."; + else if (ax==6) + desc=" (L2)."; + else if (ax==7) + desc=" (R2)."; + String str = "Device "+itos(ie.device)+", Axis "+itos(ie.joy_motion.axis)+" "+(ie.joy_motion.axis_value<0?"-":"+")+desc; action->set_text(0,str); action->set_icon(0,get_icon("JoyAxis","EditorIcons")); } break; @@ -823,6 +846,7 @@ void ProjectSettings::_autoload_edited() { String base="autoload/"+ti->get_text(0); String path = Globals::get_singleton()->get(base); + int order = Globals::get_singleton()->get_order(base); if (path.begins_with("*")) path=path.substr(1,path.length()); @@ -833,6 +857,8 @@ void ProjectSettings::_autoload_edited() { undo_redo->create_action("Toggle Autoload GlobalVar"); undo_redo->add_do_property(Globals::get_singleton(),base,path); undo_redo->add_undo_property(Globals::get_singleton(),base,Globals::get_singleton()->get(base)); + undo_redo->add_do_method(Globals::get_singleton(),"set_order",base,order); // keep order, as config order matters for these + undo_redo->add_undo_method(Globals::get_singleton(),"set_order",base,order); undo_redo->add_do_method(this,"_update_autoload"); undo_redo->add_undo_method(this,"_update_autoload"); undo_redo->add_do_method(this,"_settings_changed"); @@ -924,10 +950,12 @@ void ProjectSettings::_autoload_delete(Object *p_item,int p_column, int p_button if (p_button==0) { //delete + int order = Globals::get_singleton()->get_order(name); undo_redo->create_action("Remove Autoload"); undo_redo->add_do_property(Globals::get_singleton(),name,Variant()); undo_redo->add_undo_property(Globals::get_singleton(),name,Globals::get_singleton()->get(name)); undo_redo->add_undo_method(Globals::get_singleton(),"set_persisting",name,true); + undo_redo->add_undo_method(Globals::get_singleton(),"set_order",name,order); undo_redo->add_do_method(this,"_update_autoload"); undo_redo->add_undo_method(this,"_update_autoload"); undo_redo->add_do_method(this,"_settings_changed"); diff --git a/tools/editor/property_editor.cpp b/tools/editor/property_editor.cpp index 4b1b93ea6e..303604c2fc 100644 --- a/tools/editor/property_editor.cpp +++ b/tools/editor/property_editor.cpp @@ -714,7 +714,7 @@ bool CustomPropertyEditor::edit(Object* p_owner,const String& p_name,Variant::Ty RES r = v; if (r.is_valid() && r->get_path().is_resource_file() && r->get_import_metadata().is_valid()) { menu->add_separator(); - menu->add_icon_item(get_icon("Reload","EditorIcons"),"Re-Import",OBJ_MENU_REIMPORT); + menu->add_icon_item(get_icon("ReloadSmall","EditorIcons"),"Re-Import",OBJ_MENU_REIMPORT); } /*if (r.is_valid() && r->get_path().is_resource_file()) { menu->set_item_tooltip(1,r->get_path()); @@ -2127,11 +2127,13 @@ void PropertyEditor::_check_reload_status(const String&p_name, TreeItem* item) { bool has_reload=false; int found=-1; + bool is_disabled=false; for(int i=0;i<item->get_button_count(1);i++) { if (item->get_button_id(1,i)==3) { found=i; + is_disabled=item->is_button_disabled(1,i); break; } } @@ -2149,7 +2151,7 @@ void PropertyEditor::_check_reload_status(const String&p_name, TreeItem* item) { bool changed = _is_property_different(v,vorig,usage); - if ((found!=-1)!=changed) { + //if ((found!=-1 && !is_disabled)!=changed) { if (changed) { @@ -2158,11 +2160,9 @@ void PropertyEditor::_check_reload_status(const String&p_name, TreeItem* item) { } - } - - } - + //} + } } @@ -2176,10 +2176,20 @@ void PropertyEditor::_check_reload_status(const String&p_name, TreeItem* item) { } } + //print_line("found: "+itos(found)+" has reload: "+itos(has_reload)+" is_disabled "+itos(is_disabled)); if (found!=-1 && !has_reload) { - item->erase_button(1,found); + + if (!is_disabled) { + item->erase_button(1,found); + if (item->get_cell_mode(1)==TreeItem::CELL_MODE_RANGE && item->get_text(1)==String()) { + item->add_button(1,get_icon("ReloadEmpty","EditorIcons"),3,true); + } + } } else if (found==-1 && has_reload) { - item->add_button(1,get_icon("Reload","EditorIcons"),3); + item->add_button(1,get_icon("ReloadSmall","EditorIcons"),3); + } else if (found!=-1 && has_reload && is_disabled) { + item->erase_button(1,found); + item->add_button(1,get_icon("ReloadSmall","EditorIcons"),3); } } @@ -2348,7 +2358,7 @@ void PropertyEditor::_refresh_item(TreeItem *p_item) { if (!has_reload && found!=-1) { p_item->erase_button(1,found); } else if (has_reload && found==-1) { - p_item->add_button(1,get_icon("Reload","EditorIcons"),3); + p_item->add_button(1,get_icon("ReloadSmall","EditorIcons"),3); } #endif Dictionary d=p_item->get_metadata(0); @@ -3092,7 +3102,9 @@ void PropertyEditor::update_tree() { } bool has_reload=false; - if (_might_be_in_instance()) { + + bool mbi = _might_be_in_instance(); + if (mbi) { Variant vorig; Dictionary d=item->get_metadata(0); @@ -3103,7 +3115,7 @@ void PropertyEditor::update_tree() { if (_is_property_different(v,vorig,usage)) { //print_line("FOR "+String(p.name)+" RELOAD WITH: "+String(v)+"("+Variant::get_type_name(v.get_type())+")=="+String(vorig)+"("+Variant::get_type_name(vorig.get_type())+")"); - item->add_button(1,get_icon("Reload","EditorIcons"),3); + item->add_button(1,get_icon("ReloadSmall","EditorIcons"),3); has_reload=true; } } @@ -3115,11 +3127,16 @@ void PropertyEditor::update_tree() { Variant orig_value; if (scr->get_property_default_value(p.name,orig_value)) { if (orig_value!=obj->get(p.name)) { - item->add_button(1,get_icon("Reload","EditorIcons"),3); + item->add_button(1,get_icon("ReloadSmall","EditorIcons"),3); + has_reload=true; } } } + if (mbi && !has_reload && item->get_cell_mode(1)==TreeItem::CELL_MODE_RANGE && item->get_text(1)==String()) { + item->add_button(1,get_icon("ReloadEmpty","EditorIcons"),3,true); + } + } @@ -3180,6 +3197,9 @@ void PropertyEditor::_item_edited() { TreeItem * item = tree->get_edited(); + if (!item) + return; //it all happened too fast.. + Dictionary d = item->get_metadata(0); String name=d["name"]; @@ -3701,9 +3721,7 @@ PropertyEditor::PropertyEditor() { capitalize_paths=true; autoclear=false; - tree->set_column_title(0,"Property"); - tree->set_column_title(1,"Value"); - tree->set_column_titles_visible(true); + tree->set_column_titles_visible(false); keying=false; read_only=false; diff --git a/tools/editor/scene_tree_editor.cpp b/tools/editor/scene_tree_editor.cpp index 0260457c81..ba5cc7568b 100644 --- a/tools/editor/scene_tree_editor.cpp +++ b/tools/editor/scene_tree_editor.cpp @@ -658,6 +658,9 @@ void SceneTreeEditor::_renamed() { new_name=n->get_name(); } + if (new_name==n->get_name()) + return; + if (!undo_redo) { n->set_name( new_name ); which->set_metadata(0,n->get_path()); @@ -844,7 +847,7 @@ SceneTreeEditor::SceneTreeEditor(bool p_label,bool p_can_rename, bool p_can_open add_child( tree ); tree->connect("cell_selected", this,"_selected_changed"); - tree->connect("item_edited", this,"_renamed"); + tree->connect("item_edited", this,"_renamed",varray(),CONNECT_DEFERRED); tree->connect("multi_selected",this,"_cell_multi_selected"); tree->connect("button_pressed",this,"_cell_button_pressed"); // tree->connect("item_edited", this,"_renamed",Vector<Variant>(),true); diff --git a/tools/editor/script_editor_debugger.cpp b/tools/editor/script_editor_debugger.cpp index e727668c49..fed5ab1a16 100644 --- a/tools/editor/script_editor_debugger.cpp +++ b/tools/editor/script_editor_debugger.cpp @@ -360,7 +360,9 @@ void ScriptEditorDebugger::_parse_message(const String& p_msg,const Array& p_dat if (EditorNode::get_log()->is_hidden()) { log_forced_visible=true; - EditorNode::get_singleton()->make_bottom_panel_item_visible(EditorNode::get_log()); + if (EditorNode::get_singleton()->are_bottom_panels_hidden()) { + EditorNode::get_singleton()->make_bottom_panel_item_visible(EditorNode::get_log()); + } } EditorNode::get_log()->add_message(t); @@ -538,9 +540,6 @@ void ScriptEditorDebugger::_notification(int p_what) { forward->set_icon( get_icon("Forward","EditorIcons")); dobreak->set_icon( get_icon("Pause","EditorIcons")); docontinue->set_icon( get_icon("DebugContinue","EditorIcons")); - tb->set_normal_texture( get_icon("Close","EditorIcons")); - tb->set_hover_texture( get_icon("CloseHover","EditorIcons")); - tb->set_pressed_texture( get_icon("Close","EditorIcons")); scene_tree_refresh->set_icon( get_icon("Reload","EditorIcons")); le_set->connect("pressed",this,"_live_edit_set"); le_clear->connect("pressed",this,"_live_edit_clear"); @@ -781,13 +780,6 @@ void ScriptEditorDebugger::_stack_dump_frame_selected() { } -void ScriptEditorDebugger::_hide_request() { - - if (EditorNode::get_log()->is_visible()) - EditorNode::get_singleton()->hide_bottom_panel(); - emit_signal("show_debugger",false); -} - void ScriptEditorDebugger::_output_clear() { //output->clear(); @@ -1188,7 +1180,6 @@ void ScriptEditorDebugger::_bind_methods() { ObjectTypeDB::bind_method(_MD("debug_break"),&ScriptEditorDebugger::debug_break); ObjectTypeDB::bind_method(_MD("debug_continue"),&ScriptEditorDebugger::debug_continue); ObjectTypeDB::bind_method(_MD("_output_clear"),&ScriptEditorDebugger::_output_clear); - ObjectTypeDB::bind_method(_MD("_hide_request"),&ScriptEditorDebugger::_hide_request); ObjectTypeDB::bind_method(_MD("_performance_draw"),&ScriptEditorDebugger::_performance_draw); ObjectTypeDB::bind_method(_MD("_performance_select"),&ScriptEditorDebugger::_performance_select); ObjectTypeDB::bind_method(_MD("_scene_tree_request"),&ScriptEditorDebugger::_scene_tree_request); @@ -1224,13 +1215,6 @@ ScriptEditorDebugger::ScriptEditorDebugger(EditorNode *p_editor){ tabs->set_area_as_parent_rect(); add_child(tabs); - tb = memnew( TextureButton ); - tb->connect("pressed",this,"_hide_request"); - tb->set_anchor_and_margin(MARGIN_LEFT,ANCHOR_END,20); - tb->set_margin(MARGIN_TOP,2); - add_child(tb); - - VBoxContainer *vbc = memnew( VBoxContainer ); vbc->set_name("Debugger"); diff --git a/tools/editor/script_editor_debugger.h b/tools/editor/script_editor_debugger.h index 0be311a990..ecd0494955 100644 --- a/tools/editor/script_editor_debugger.h +++ b/tools/editor/script_editor_debugger.h @@ -76,9 +76,6 @@ class ScriptEditorDebugger : public Control { - TextureButton *tb; - - TabContainer *tabs; LineEdit *reason; @@ -129,7 +126,6 @@ class ScriptEditorDebugger : public Control { void _performance_select(Object *, int, bool); void _stack_dump_frame_selected(); void _output_clear(); - void _hide_request(); void _scene_tree_request(); void _parse_message(const String& p_msg,const Array& p_data); diff --git a/tools/editor/settings_config_dialog.cpp b/tools/editor/settings_config_dialog.cpp index ebbc488ff2..86a3ab7001 100644 --- a/tools/editor/settings_config_dialog.cpp +++ b/tools/editor/settings_config_dialog.cpp @@ -321,12 +321,12 @@ EditorSettingsDialog::EditorSettingsDialog() { vbc->add_child(hbc); hbc->add_child( memnew( Label("Plugin List: "))); hbc->add_spacer(); - Button *load = memnew( Button ); - load->set_text("Load.."); + //Button *load = memnew( Button ); + //load->set_text("Load.."); + //hbc->add_child(load); Button *rescan = memnew( Button ); rescan_plugins=rescan; rescan_plugins->connect("pressed",this,"_rescan_plugins"); - hbc->add_child(load); hbc->add_child(rescan); plugins = memnew( Tree ); MarginContainer *mc = memnew( MarginContainer); diff --git a/tools/pe_bliss/README b/tools/pe_bliss/README deleted file mode 100644 index d5d1355444..0000000000 --- a/tools/pe_bliss/README +++ /dev/null @@ -1,84 +0,0 @@ -/*************************************************************************/ -/* Copyright (c) 2015 dx, http://kaimi.ru */ -/* */ -/* Permission is hereby granted, free of charge, to any person */ -/* obtaining a copy of this software and associated documentation */ -/* files (the "Software"), to deal in the Software without */ -/* restriction, including without limitation the rights to use, */ -/* copy, modify, merge, publish, distribute, sublicense, and/or */ -/* sell copies of the Software, and to permit persons to whom the */ -/* Software is furnished to do so, subject to the following conditions: */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - - -Открытая бесплатная библиотека для работы с PE-файлами PE Bliss. -Бесплатна к использованию, модификации и распространению. -Автор: DX -(c) DX 2011-2012, kaimi.ru - -Совместимость: Windows, Linux - -Возможности: -[+] Создание PE или PE+ файла с нуля -[+] Чтение 32-разрядных и 64-разрядных PE-файлов (PE, PE+) и единообразная работа с ними -[+] Пересборка 32-разрядных и 64-разрядных PE-файлов -[+] Работа с директориями и заголовками -[+] Конвертирование адресов -[+] Чтение и редактирование секций PE-файла -[+] Чтение и редактирование таблицы импортов -[+] Чтение и редактирование таблицы экспортов -[+] Чтение и редактирование таблиц релокаций -[+] Чтение и редактирование ресурсов -[+] Чтение и редактирование TLS -[+] Чтение и редактирование конфигурации образа (image config) -[+] Чтение базовой информации .NET -[+] Чтение и редактирование информации о привязанном импорте -[+] Чтение директории исключений (только PE+) -[+] Чтение отладочной директории с расширенной информацией -[+] Вычисление энтропии -[+] Изменение файлового выравнивания -[+] Изменение базового адреса загрузки -[+] Работа с DOS Stub'ом и Rich overlay -[+] Высокоуровневое чтение ресурсов: картинки, иконки, курсоры, информация о версии, строковые таблицы, таблицы сообщений -[+] Высокоуровневое редактирование ресурсов: картинки, иконки, курсоры, информация о версии - -[English] -Open a free library for working with PE-file PE Bliss. -Free to use, modify, and distribute. -Author: DX -(c) DX 2011-2012, kaimi.ru -Compatibility: Windows, Linux - -### Capabilities: -[+] Creation of PE or PE + file from scratch -[+] Reading the 32-bit and 64-bit PE-file (PE, PE +) and uniform working with them -[+] Rebuild 32-bit and 64-bit PE-files -[+] Working with the directors and titles -[+] Converting addresses -[+] Reading and editing sections of PE-file -[+] Reading and editing the import table -[+] Reading and editing tables exports -[+] Reading and editing tables relocations -[+] Reading and editing resources -[+] Reading and editing TLS -[+] Reading and editing the configuration of the image (image config) -[+] Reading data base .NET -[+] Reading and editing information about tethered import -[+] Read the directory exceptions (only PE +) -[+] Read debug directories with extended information -[+] The calculation of entropy -[+] Changing file alignment -[+] Change the base load address -[+] Support of DOS Stub'om and Rich overlay -[+] High-level reading resources: images, icons, cursors, version information, string tables, message table -[+] High-level editing resources: images, icons, cursors, version information
\ No newline at end of file diff --git a/tools/pe_bliss/SCsub b/tools/pe_bliss/SCsub deleted file mode 100644 index 34524f10ef..0000000000 --- a/tools/pe_bliss/SCsub +++ /dev/null @@ -1,5 +0,0 @@ -Import('env') - -env.add_source_files(env.tool_sources,"*.cpp") - -Export('env') diff --git a/tools/pe_bliss/entropy.cpp b/tools/pe_bliss/entropy.cpp deleted file mode 100644 index acefa63e83..0000000000 --- a/tools/pe_bliss/entropy.cpp +++ /dev/null @@ -1,111 +0,0 @@ -/*************************************************************************/ -/* Copyright (c) 2015 dx, http://kaimi.ru */ -/* */ -/* Permission is hereby granted, free of charge, to any person */ -/* obtaining a copy of this software and associated documentation */ -/* files (the "Software"), to deal in the Software without */ -/* restriction, including without limitation the rights to use, */ -/* copy, modify, merge, publish, distribute, sublicense, and/or */ -/* sell copies of the Software, and to permit persons to whom the */ -/* Software is furnished to do so, subject to the following conditions: */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#include <cmath> -#include "entropy.h" -#include "utils.h" - -namespace pe_bliss -{ -//Calculates entropy for PE image section -double entropy_calculator::calculate_entropy(const section& s) -{ - if(s.get_raw_data().empty()) //Don't count entropy for empty sections - throw pe_exception("Section is empty", pe_exception::section_is_empty); - - return calculate_entropy(s.get_raw_data().data(), s.get_raw_data().length()); -} - -//Calculates entropy for istream (from current position of stream) -double entropy_calculator::calculate_entropy(std::istream& file) -{ - uint32_t byte_count[256] = {0}; //Byte count for each of 255 bytes - - if(file.bad()) - throw pe_exception("Stream is bad", pe_exception::stream_is_bad); - - std::streamoff pos = file.tellg(); - - std::streamoff length = pe_utils::get_file_size(file); - length -= file.tellg(); - - if(!length) //Don't calculate entropy for empty buffers - throw pe_exception("Data length is zero", pe_exception::data_is_empty); - - //Count bytes - for(std::streamoff i = 0; i != length; ++i) - ++byte_count[static_cast<unsigned char>(file.get())]; - - file.seekg(pos); - - return calculate_entropy(byte_count, length); -} - -//Calculates entropy for data block -double entropy_calculator::calculate_entropy(const char* data, size_t length) -{ - uint32_t byte_count[256] = {0}; //Byte count for each of 255 bytes - - if(!length) //Don't calculate entropy for empty buffers - throw pe_exception("Data length is zero", pe_exception::data_is_empty); - - //Count bytes - for(size_t i = 0; i != length; ++i) - ++byte_count[static_cast<unsigned char>(data[i])]; - - return calculate_entropy(byte_count, length); -} - -//Calculates entropy for this PE file (only section data) -double entropy_calculator::calculate_entropy(const pe_base& pe) -{ - uint32_t byte_count[256] = {0}; //Byte count for each of 255 bytes - - size_t total_data_length = 0; - - //Count bytes for each section - for(section_list::const_iterator it = pe.get_image_sections().begin(); it != pe.get_image_sections().end(); ++it) - { - const std::string& data = (*it).get_raw_data(); - size_t length = data.length(); - total_data_length += length; - for(size_t i = 0; i != length; ++i) - ++byte_count[static_cast<unsigned char>(data[i])]; - } - - return calculate_entropy(byte_count, total_data_length); -} - -//Calculates entropy from bytes count -double entropy_calculator::calculate_entropy(const uint32_t byte_count[256], std::streamoff total_length) -{ - double entropy = 0.; //Entropy result value - //Calculate entropy - for(uint32_t i = 0; i < 256; ++i) - { - double temp = static_cast<double>(byte_count[i]) / total_length; - if(temp > 0.) - entropy += std::abs(temp * (std::log(temp) * pe_utils::log_2)); - } - - return entropy; -} -} diff --git a/tools/pe_bliss/entropy.h b/tools/pe_bliss/entropy.h deleted file mode 100644 index 7d225a3e32..0000000000 --- a/tools/pe_bliss/entropy.h +++ /dev/null @@ -1,51 +0,0 @@ -/*************************************************************************/ -/* Copyright (c) 2015 dx, http://kaimi.ru */ -/* */ -/* Permission is hereby granted, free of charge, to any person */ -/* obtaining a copy of this software and associated documentation */ -/* files (the "Software"), to deal in the Software without */ -/* restriction, including without limitation the rights to use, */ -/* copy, modify, merge, publish, distribute, sublicense, and/or */ -/* sell copies of the Software, and to permit persons to whom the */ -/* Software is furnished to do so, subject to the following conditions: */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#pragma once -#include <istream> -#include "pe_base.h" - -namespace pe_bliss -{ -class entropy_calculator -{ -public: - //Calculates entropy for PE image section - static double calculate_entropy(const section& s); - - //Calculates entropy for istream (from current position of stream) - static double calculate_entropy(std::istream& file); - - //Calculates entropy for data block - static double calculate_entropy(const char* data, size_t length); - - //Calculates entropy for this PE file (only section data) - static double calculate_entropy(const pe_base& pe); - -private: - entropy_calculator(); - entropy_calculator(const entropy_calculator&); - entropy_calculator& operator=(const entropy_calculator&); - - //Calculates entropy from bytes count - static double calculate_entropy(const uint32_t byte_count[256], std::streamoff total_length); -}; -} diff --git a/tools/pe_bliss/file_version_info.cpp b/tools/pe_bliss/file_version_info.cpp deleted file mode 100644 index 3f2ba454b4..0000000000 --- a/tools/pe_bliss/file_version_info.cpp +++ /dev/null @@ -1,440 +0,0 @@ -/*************************************************************************/ -/* Copyright (c) 2015 dx, http://kaimi.ru */ -/* */ -/* Permission is hereby granted, free of charge, to any person */ -/* obtaining a copy of this software and associated documentation */ -/* files (the "Software"), to deal in the Software without */ -/* restriction, including without limitation the rights to use, */ -/* copy, modify, merge, publish, distribute, sublicense, and/or */ -/* sell copies of the Software, and to permit persons to whom the */ -/* Software is furnished to do so, subject to the following conditions: */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#include "file_version_info.h" -#include "pe_structures.h" - -namespace pe_bliss -{ -using namespace pe_win; - -//Default constructor -file_version_info::file_version_info() - :file_version_ms_(0), file_version_ls_(0), - product_version_ms_(0), product_version_ls_(0), - file_flags_(0), - file_os_(0), - file_type_(0), file_subtype_(0), - file_date_ms_(0), file_date_ls_(0) -{} - -//Constructor from Windows fixed version info structure -file_version_info::file_version_info(const vs_fixedfileinfo& info) - :file_version_ms_(info.dwFileVersionMS), file_version_ls_(info.dwFileVersionLS), - product_version_ms_(info.dwProductVersionMS), product_version_ls_(info.dwProductVersionLS), - file_flags_(info.dwFileFlags), - file_os_(info.dwFileOS), - file_type_(info.dwFileType), file_subtype_(info.dwFileSubtype), - file_date_ms_(info.dwFileDateMS), file_date_ls_(info.dwFileDateLS) -{} - -//Returns true if file is debug-built -bool file_version_info::is_debug() const -{ - return file_flags_ & vs_ff_debug ? true : false; -} - -//Returns true if file is release-built -bool file_version_info::is_prerelease() const -{ - return file_flags_ & vs_ff_prerelease ? true : false; -} - -//Returns true if file is patched -bool file_version_info::is_patched() const -{ - return file_flags_ & vs_ff_patched ? true : false; -} - -//Returns true if private build -bool file_version_info::is_private_build() const -{ - return file_flags_ & vs_ff_privatebuild ? true : false; -} - -//Returns true if special build -bool file_version_info::is_special_build() const -{ - return file_flags_ & vs_ff_specialbuild ? true : false; -} - -//Returns true if info inferred -bool file_version_info::is_info_inferred() const -{ - return file_flags_ & vs_ff_infoinferred ? true : false; -} - -//Retuens file flags (raw DWORD) -uint32_t file_version_info::get_file_flags() const -{ - return file_flags_; -} - -//Returns file version most significant DWORD -uint32_t file_version_info::get_file_version_ms() const -{ - return file_version_ms_; -} - -//Returns file version least significant DWORD -uint32_t file_version_info::get_file_version_ls() const -{ - return file_version_ls_; -} - -//Returns product version most significant DWORD -uint32_t file_version_info::get_product_version_ms() const -{ - return product_version_ms_; -} - -//Returns product version least significant DWORD -uint32_t file_version_info::get_product_version_ls() const -{ - return product_version_ls_; -} - -//Returns file OS type (raw DWORD) -uint32_t file_version_info::get_file_os_raw() const -{ - return file_os_; -} - -//Returns file OS type -file_version_info::file_os_type file_version_info::get_file_os() const -{ - //Determine file operation system type - switch(file_os_) - { - case vos_dos: - return file_os_dos; - - case vos_os216: - return file_os_os216; - - case vos_os232: - return file_os_os232; - - case vos_nt: - return file_os_nt; - - case vos_wince: - return file_os_wince; - - case vos__windows16: - return file_os_win16; - - case vos__pm16: - return file_os_pm16; - - case vos__pm32: - return file_os_pm32; - - case vos__windows32: - return file_os_win32; - - case vos_dos_windows16: - return file_os_dos_win16; - - case vos_dos_windows32: - return file_os_dos_win32; - - case vos_os216_pm16: - return file_os_os216_pm16; - - case vos_os232_pm32: - return file_os_os232_pm32; - - case vos_nt_windows32: - return file_os_nt_win32; - } - - return file_os_unknown; -} - -//Returns file type (raw DWORD) -uint32_t file_version_info::get_file_type_raw() const -{ - return file_type_; -} - -//Returns file type -file_version_info::file_type file_version_info::get_file_type() const -{ - //Determine file type - switch(file_type_) - { - case vft_app: - return file_type_application; - - case vft_dll: - return file_type_dll; - - case vft_drv: - return file_type_driver; - - case vft_font: - return file_type_font; - - case vft_vxd: - return file_type_vxd; - - case vft_static_lib: - return file_type_static_lib; - } - - return file_type_unknown; -} - -//Returns file subtype (usually non-zero for drivers and fonts) -uint32_t file_version_info::get_file_subtype() const -{ - return file_subtype_; -} - -//Returns file date most significant DWORD -uint32_t file_version_info::get_file_date_ms() const -{ - return file_date_ms_; -} - -//Returns file date least significant DWORD -uint32_t file_version_info::get_file_date_ls() const -{ - return file_date_ls_; -} - -//Helper to set file flag -void file_version_info::set_file_flag(uint32_t flag) -{ - file_flags_ |= flag; -} - -//Helper to clear file flag -void file_version_info::clear_file_flag(uint32_t flag) -{ - file_flags_ &= ~flag; -} - -//Helper to set or clear file flag -void file_version_info::set_file_flag(uint32_t flag, bool set_flag) -{ - set_flag ? set_file_flag(flag) : clear_file_flag(flag); -} - -//Sets if file is debug-built -void file_version_info::set_debug(bool debug) -{ - set_file_flag(vs_ff_debug, debug); -} - -//Sets if file is prerelease -void file_version_info::set_prerelease(bool prerelease) -{ - set_file_flag(vs_ff_prerelease, prerelease); -} - -//Sets if file is patched -void file_version_info::set_patched(bool patched) -{ - set_file_flag(vs_ff_patched, patched); -} - -//Sets if private build -void file_version_info::set_private_build(bool private_build) -{ - set_file_flag(vs_ff_privatebuild, private_build); -} - -//Sets if special build -void file_version_info::set_special_build(bool special_build) -{ - set_file_flag(vs_ff_specialbuild, special_build); -} - -//Sets if info inferred -void file_version_info::set_info_inferred(bool info_inferred) -{ - set_file_flag(vs_ff_infoinferred, info_inferred); -} - -//Sets flags (raw DWORD) -void file_version_info::set_file_flags(uint32_t file_flags) -{ - file_flags_ = file_flags; -} - -//Sets file version most significant DWORD -void file_version_info::set_file_version_ms(uint32_t file_version_ms) -{ - file_version_ms_ = file_version_ms; -} - -//Sets file version least significant DWORD -void file_version_info::set_file_version_ls(uint32_t file_version_ls) -{ - file_version_ls_ = file_version_ls; -} - -//Sets product version most significant DWORD -void file_version_info::set_product_version_ms(uint32_t product_version_ms) -{ - product_version_ms_ = product_version_ms; -} - -//Sets product version least significant DWORD -void file_version_info::set_product_version_ls(uint32_t product_version_ls) -{ - product_version_ls_ = product_version_ls; -} - -//Sets file OS type (raw DWORD) -void file_version_info::set_file_os_raw(uint32_t file_os) -{ - file_os_ = file_os; -} - -//Sets file OS type -void file_version_info::set_file_os(file_os_type file_os) -{ - //Determine file operation system type - switch(file_os) - { - case file_os_dos: - file_os_ = vos_dos; - return; - - case file_os_os216: - file_os_ = vos_os216; - return; - - case file_os_os232: - file_os_ = vos_os232; - return; - - case file_os_nt: - file_os_ = vos_nt; - return; - - case file_os_wince: - file_os_ = vos_wince; - return; - - case file_os_win16: - file_os_ = vos__windows16; - return; - - case file_os_pm16: - file_os_ = vos__pm16; - return; - - case file_os_pm32: - file_os_ = vos__pm32; - return; - - case file_os_win32: - file_os_ = vos__windows32; - return; - - case file_os_dos_win16: - file_os_ = vos_dos_windows16; - return; - - case file_os_dos_win32: - file_os_ = vos_dos_windows32; - return; - - case file_os_os216_pm16: - file_os_ = vos_os216_pm16; - return; - - case file_os_os232_pm32: - file_os_ = vos_os232_pm32; - return; - - case file_os_nt_win32: - file_os_ = vos_nt_windows32; - return; - - default: - return; - } -} - -//Sets file type (raw DWORD) -void file_version_info::set_file_type_raw(uint32_t file_type) -{ - file_type_ = file_type; -} - -//Sets file type -void file_version_info::set_file_type(file_type file_type) -{ - //Determine file type - switch(file_type) - { - case file_type_application: - file_type_ = vft_app; - return; - - case file_type_dll: - file_type_ = vft_dll; - return; - - case file_type_driver: - file_type_ = vft_drv; - return; - - case file_type_font: - file_type_ = vft_font; - return; - - case file_type_vxd: - file_type_ = vft_vxd; - return; - - case file_type_static_lib: - file_type_ = vft_static_lib; - return; - - default: - return; - } -} - -//Sets file subtype (usually non-zero for drivers and fonts) -void file_version_info::set_file_subtype(uint32_t file_subtype) -{ - file_subtype_ = file_subtype; -} - -//Sets file date most significant DWORD -void file_version_info::set_file_date_ms(uint32_t file_date_ms) -{ - file_date_ms_ = file_date_ms; -} - -//Sets file date least significant DWORD -void file_version_info::set_file_date_ls(uint32_t file_date_ls) -{ - file_date_ls_ = file_date_ls; -} -} diff --git a/tools/pe_bliss/file_version_info.h b/tools/pe_bliss/file_version_info.h deleted file mode 100644 index d898351ba1..0000000000 --- a/tools/pe_bliss/file_version_info.h +++ /dev/null @@ -1,199 +0,0 @@ -/*************************************************************************/ -/* Copyright (c) 2015 dx, http://kaimi.ru */ -/* */ -/* Permission is hereby granted, free of charge, to any person */ -/* obtaining a copy of this software and associated documentation */ -/* files (the "Software"), to deal in the Software without */ -/* restriction, including without limitation the rights to use, */ -/* copy, modify, merge, publish, distribute, sublicense, and/or */ -/* sell copies of the Software, and to permit persons to whom the */ -/* Software is furnished to do so, subject to the following conditions: */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#pragma once -#include <string> -#include <map> -#include "stdint_defs.h" -#include "pe_structures.h" - -namespace pe_bliss -{ -//Structure representing fixed file version info -class file_version_info -{ -public: - //Enumeration of file operating system types - enum file_os_type - { - file_os_unknown, - file_os_dos, - file_os_os216, - file_os_os232, - file_os_nt, - file_os_wince, - file_os_win16, - file_os_pm16, - file_os_pm32, - file_os_win32, - file_os_dos_win16, - file_os_dos_win32, - file_os_os216_pm16, - file_os_os232_pm32, - file_os_nt_win32 - }; - - //Enumeration of file types - enum file_type - { - file_type_unknown, - file_type_application, - file_type_dll, - file_type_driver, - file_type_font, - file_type_vxd, - file_type_static_lib - }; - -public: - //Default constructor - file_version_info(); - //Constructor from Windows fixed version info structure - explicit file_version_info(const pe_win::vs_fixedfileinfo& info); - -public: //Getters - //Returns true if file is debug-built - bool is_debug() const; - //Returns true if file is prerelease - bool is_prerelease() const; - //Returns true if file is patched - bool is_patched() const; - //Returns true if private build - bool is_private_build() const; - //Returns true if special build - bool is_special_build() const; - //Returns true if info inferred - bool is_info_inferred() const; - //Retuens file flags (raw DWORD) - uint32_t get_file_flags() const; - - //Returns file version most significant DWORD - uint32_t get_file_version_ms() const; - //Returns file version least significant DWORD - uint32_t get_file_version_ls() const; - //Returns product version most significant DWORD - uint32_t get_product_version_ms() const; - //Returns product version least significant DWORD - uint32_t get_product_version_ls() const; - - //Returns file OS type (raw DWORD) - uint32_t get_file_os_raw() const; - //Returns file OS type - file_os_type get_file_os() const; - - //Returns file type (raw DWORD) - uint32_t get_file_type_raw() const; - //Returns file type - file_type get_file_type() const; - - //Returns file subtype (usually non-zero for drivers and fonts) - uint32_t get_file_subtype() const; - - //Returns file date most significant DWORD - uint32_t get_file_date_ms() const; - //Returns file date least significant DWORD - uint32_t get_file_date_ls() const; - - //Returns file version string - template<typename T> - const std::basic_string<T> get_file_version_string() const - { - return get_version_string<T>(file_version_ms_, file_version_ls_); - } - - //Returns product version string - template<typename T> - const std::basic_string<T> get_product_version_string() const - { - return get_version_string<T>(product_version_ms_, product_version_ls_); - } - -public: //Setters - //Sets if file is debug-built - void set_debug(bool debug); - //Sets if file is prerelease - void set_prerelease(bool prerelease); - //Sets if file is patched - void set_patched(bool patched); - //Sets if private build - void set_private_build(bool private_build); - //Sets if special build - void set_special_build(bool special_build); - //Sets if info inferred - void set_info_inferred(bool info_inferred); - //Sets flags (raw DWORD) - void set_file_flags(uint32_t file_flags); - - //Sets file version most significant DWORD - void set_file_version_ms(uint32_t file_version_ms); - //Sets file version least significant DWORD - void set_file_version_ls(uint32_t file_version_ls); - //Sets product version most significant DWORD - void set_product_version_ms(uint32_t product_version_ms); - //Sets product version least significant DWORD - void set_product_version_ls(uint32_t product_version_ls); - - //Sets file OS type (raw DWORD) - void set_file_os_raw(uint32_t file_os); - //Sets file OS type - void set_file_os(file_os_type file_os); - - //Sets file type (raw DWORD) - void set_file_type_raw(uint32_t file_type); - //Sets file type - void set_file_type(file_type file_type); - - //Sets file subtype (usually non-zero for drivers and fonts) - void set_file_subtype(uint32_t file_subtype); - - //Sets file date most significant DWORD - void set_file_date_ms(uint32_t file_date_ms); - //Sets file date least significant DWORD - void set_file_date_ls(uint32_t file_date_ls); - -private: - //Helper to convert version DWORDs to string - template<typename T> - static const std::basic_string<T> get_version_string(uint32_t ms, uint32_t ls) - { - std::basic_stringstream<T> ss; - ss << (ms >> 16) << static_cast<T>(L'.') - << (ms & 0xFFFF) << static_cast<T>(L'.') - << (ls >> 16) << static_cast<T>(L'.') - << (ls & 0xFFFF); - return ss.str(); - } - - //Helper to set file flag - void set_file_flag(uint32_t flag); - //Helper to clear file flag - void clear_file_flag(uint32_t flag); - //Helper to set or clear file flag - void set_file_flag(uint32_t flag, bool set_flag); - - uint32_t file_version_ms_, file_version_ls_, - product_version_ms_, product_version_ls_; - uint32_t file_flags_; - uint32_t file_os_; - uint32_t file_type_, file_subtype_; - uint32_t file_date_ms_, file_date_ls_; -}; -} diff --git a/tools/pe_bliss/message_table.cpp b/tools/pe_bliss/message_table.cpp deleted file mode 100644 index 909be5d494..0000000000 --- a/tools/pe_bliss/message_table.cpp +++ /dev/null @@ -1,81 +0,0 @@ -/*************************************************************************/ -/* Copyright (c) 2015 dx, http://kaimi.ru */ -/* */ -/* Permission is hereby granted, free of charge, to any person */ -/* obtaining a copy of this software and associated documentation */ -/* files (the "Software"), to deal in the Software without */ -/* restriction, including without limitation the rights to use, */ -/* copy, modify, merge, publish, distribute, sublicense, and/or */ -/* sell copies of the Software, and to permit persons to whom the */ -/* Software is furnished to do so, subject to the following conditions: */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#include "message_table.h" -#include "utils.h" - -namespace pe_bliss -{ -//Default constructor -message_table_item::message_table_item() - :unicode_(false) -{} - -//Constructor from ANSI string -message_table_item::message_table_item(const std::string& str) - :unicode_(false), ansi_str_(str) -{ - pe_utils::strip_nullbytes(ansi_str_); -} - -//Constructor from UNICODE string -message_table_item::message_table_item(const std::wstring& str) - :unicode_(true), unicode_str_(str) -{ - pe_utils::strip_nullbytes(unicode_str_); -} - -//Returns true if contained string is unicode -bool message_table_item::is_unicode() const -{ - return unicode_; -} - -//Returns ANSI string -const std::string& message_table_item::get_ansi_string() const -{ - return ansi_str_; -} - -//Returns UNICODE string -const std::wstring& message_table_item::get_unicode_string() const -{ - return unicode_str_; -} - -//Sets ANSI string (clears UNICODE one) -void message_table_item::set_string(const std::string& str) -{ - ansi_str_ = str; - pe_utils::strip_nullbytes(ansi_str_); - unicode_str_.clear(); - unicode_ = false; -} - -//Sets UNICODE string (clears ANSI one) -void message_table_item::set_string(const std::wstring& str) -{ - unicode_str_ = str; - pe_utils::strip_nullbytes(unicode_str_); - ansi_str_.clear(); - unicode_ = true; -} -} diff --git a/tools/pe_bliss/message_table.h b/tools/pe_bliss/message_table.h deleted file mode 100644 index 5a3feb32c1..0000000000 --- a/tools/pe_bliss/message_table.h +++ /dev/null @@ -1,56 +0,0 @@ -/*************************************************************************/ -/* Copyright (c) 2015 dx, http://kaimi.ru */ -/* */ -/* Permission is hereby granted, free of charge, to any person */ -/* obtaining a copy of this software and associated documentation */ -/* files (the "Software"), to deal in the Software without */ -/* restriction, including without limitation the rights to use, */ -/* copy, modify, merge, publish, distribute, sublicense, and/or */ -/* sell copies of the Software, and to permit persons to whom the */ -/* Software is furnished to do so, subject to the following conditions: */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#pragma once -#include <string> -#include <map> -#include "stdint_defs.h" - -namespace pe_bliss -{ -//Structure representing message table string -class message_table_item -{ -public: - //Default constructor - message_table_item(); - //Constructors from ANSI and UNICODE strings - explicit message_table_item(const std::string& str); - explicit message_table_item(const std::wstring& str); - - //Returns true if string is UNICODE - bool is_unicode() const; - //Returns ANSI string - const std::string& get_ansi_string() const; - //Returns UNICODE string - const std::wstring& get_unicode_string() const; - -public: - //Sets ANSI or UNICODE string - void set_string(const std::string& str); - void set_string(const std::wstring& str); - -private: - bool unicode_; - std::string ansi_str_; - std::wstring unicode_str_; -}; -} diff --git a/tools/pe_bliss/pe_base.cpp b/tools/pe_bliss/pe_base.cpp deleted file mode 100644 index 97baa17cb3..0000000000 --- a/tools/pe_bliss/pe_base.cpp +++ /dev/null @@ -1,1680 +0,0 @@ -/*************************************************************************/ -/* Copyright (c) 2015 dx, http://kaimi.ru */ -/* */ -/* Permission is hereby granted, free of charge, to any person */ -/* obtaining a copy of this software and associated documentation */ -/* files (the "Software"), to deal in the Software without */ -/* restriction, including without limitation the rights to use, */ -/* copy, modify, merge, publish, distribute, sublicense, and/or */ -/* sell copies of the Software, and to permit persons to whom the */ -/* Software is furnished to do so, subject to the following conditions: */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#include <string> -#include <vector> -#include <istream> -#include <ostream> -#include <algorithm> -#include <cmath> -#include <set> -#include <string.h> -#include "pe_exception.h" -#include "pe_base.h" - -namespace pe_bliss -{ -using namespace pe_win; - -//Constructor -pe_base::pe_base(std::istream& file, const pe_properties& props, bool read_debug_raw_data) -{ - props_ = props.duplicate().release(); - - //Save istream state - std::ios_base::iostate state = file.exceptions(); - std::streamoff old_offset = file.tellg(); - - try - { - file.exceptions(std::ios::goodbit); - //Read DOS header, PE headers and section data - read_dos_header(file); - read_pe(file, read_debug_raw_data); - } - catch(const std::exception&) - { - //If something went wrong, restore istream state - file.seekg(old_offset); - file.exceptions(state); - file.clear(); - //Rethrow - throw; - } - - //Restore istream state - file.seekg(old_offset); - file.exceptions(state); - file.clear(); -} - -pe_base::pe_base(const pe_properties& props, uint32_t section_alignment, bool dll, uint16_t subsystem) -{ - props_ = props.duplicate().release(); - props_->create_pe(section_alignment, subsystem); - - has_overlay_ = false; - memset(&dos_header_, 0, sizeof(dos_header_)); - - dos_header_.e_magic = 0x5A4D; //"MZ" - //Magic numbers from MSVC++ build - dos_header_.e_maxalloc = 0xFFFF; - dos_header_.e_cblp = 0x90; - dos_header_.e_cp = 3; - dos_header_.e_cparhdr = 4; - dos_header_.e_sp = 0xB8; - dos_header_.e_lfarlc = 64; - - set_characteristics(image_file_executable_image | image_file_relocs_stripped); - - if(get_pe_type() == pe_type_32) - set_characteristics_flags(image_file_32bit_machine); - - if(dll) - set_characteristics_flags(image_file_dll); - - set_subsystem_version(5, 1); //WinXP - set_os_version(5, 1); //WinXP -} - -pe_base::pe_base(const pe_base& pe) - :dos_header_(pe.dos_header_), - rich_overlay_(pe.rich_overlay_), - sections_(pe.sections_), - has_overlay_(pe.has_overlay_), - full_headers_data_(pe.full_headers_data_), - debug_data_(pe.debug_data_), - props_(0) -{ - props_ = pe.props_->duplicate().release(); -} - -pe_base& pe_base::operator=(const pe_base& pe) -{ - dos_header_ = pe.dos_header_; - rich_overlay_ = pe.rich_overlay_; - sections_ = pe.sections_; - has_overlay_ = pe.has_overlay_; - full_headers_data_ = pe.full_headers_data_; - debug_data_ = pe.debug_data_; - delete props_; - props_ = 0; - props_ = pe.props_->duplicate().release(); - - return *this; -} - -pe_base::~pe_base() -{ - delete props_; -} - -//Returns dos header -const image_dos_header& pe_base::get_dos_header() const -{ - return dos_header_; -} - -//Returns dos header -image_dos_header& pe_base::get_dos_header() -{ - return dos_header_; -} - -//Returns PE headers start position (e_lfanew) -int32_t pe_base::get_pe_header_start() const -{ - return dos_header_.e_lfanew; -} - -//Strips MSVC stub overlay -void pe_base::strip_stub_overlay() -{ - rich_overlay_.clear(); -} - -//Fills MSVC stub overlay with character c -void pe_base::fill_stub_overlay(char c) -{ - if(rich_overlay_.length()) - rich_overlay_.assign(rich_overlay_.length(), c); -} - -//Sets stub MSVS overlay -void pe_base::set_stub_overlay(const std::string& data) -{ - rich_overlay_ = data; -} - -//Returns stub overlay -const std::string& pe_base::get_stub_overlay() const -{ - return rich_overlay_; -} - -//Realigns all sections -void pe_base::realign_all_sections() -{ - for(unsigned int i = 0; i < sections_.size(); i++) - realign_section(i); -} - -//Returns number of sections from PE header -uint16_t pe_base::get_number_of_sections() const -{ - return props_->get_number_of_sections(); -} - -//Updates number of sections in PE header -uint16_t pe_base::update_number_of_sections() -{ - uint16_t new_number = static_cast<uint16_t>(sections_.size()); - props_->set_number_of_sections(new_number); - return new_number; -} - -//Returns section alignment -uint32_t pe_base::get_section_alignment() const -{ - return props_->get_section_alignment(); -} - -//Returns image sections list -section_list& pe_base::get_image_sections() -{ - return sections_; -} - -//Returns image sections list -const section_list& pe_base::get_image_sections() const -{ - return sections_; -} - -//Realigns section by index -void pe_base::realign_section(uint32_t index) -{ - //Check index - if(sections_.size() <= index) - throw pe_exception("Section not found", pe_exception::section_not_found); - - //Get section iterator - section_list::iterator it = sections_.begin() + index; - section& s = *it; - - //Calculate, how many null bytes we have in the end of raw section data - std::size_t strip = 0; - for(std::size_t i = (*it).get_raw_data().length(); i >= 1; --i) - { - if(s.get_raw_data()[i - 1] == 0) - strip++; - else - break; - } - - if(it == sections_.end() - 1) //If we're realigning the last section - { - //We can strip ending null bytes - s.set_size_of_raw_data(static_cast<uint32_t>(s.get_raw_data().length() - strip)); - s.get_raw_data().resize(s.get_raw_data().length() - strip, 0); - } - else - { - //Else just set size of raw data - uint32_t raw_size_aligned = s.get_aligned_raw_size(get_file_alignment()); - s.set_size_of_raw_data(raw_size_aligned); - s.get_raw_data().resize(raw_size_aligned, 0); - } -} - -//Returns file alignment -uint32_t pe_base::get_file_alignment() const -{ - return props_->get_file_alignment(); -} - -//Sets file alignment -void pe_base::set_file_alignment(uint32_t alignment) -{ - //Check alignment - if(alignment < minimum_file_alignment) - throw pe_exception("File alignment can't be less than 512", pe_exception::incorrect_file_alignment); - - if(!pe_utils::is_power_of_2(alignment)) - throw pe_exception("File alignment must be a power of 2", pe_exception::incorrect_file_alignment); - - if(alignment > get_section_alignment()) - throw pe_exception("File alignment must be <= section alignment", pe_exception::incorrect_file_alignment); - - //Set file alignment without any additional checks - set_file_alignment_unchecked(alignment); -} - -//Returns size of image -uint32_t pe_base::get_size_of_image() const -{ - return props_->get_size_of_image(); -} - -//Returns image entry point -uint32_t pe_base::get_ep() const -{ - return props_->get_ep(); -} - -//Sets image entry point (just a value of PE header) -void pe_base::set_ep(uint32_t new_ep) -{ - props_->set_ep(new_ep); -} - -//Returns number of RVA and sizes (number of DATA_DIRECTORY entries) -uint32_t pe_base::get_number_of_rvas_and_sizes() const -{ - return props_->get_number_of_rvas_and_sizes(); -} - -//Sets number of RVA and sizes (number of DATA_DIRECTORY entries) -void pe_base::set_number_of_rvas_and_sizes(uint32_t number) -{ - props_->set_number_of_rvas_and_sizes(number); -} - -//Returns PE characteristics -uint16_t pe_base::get_characteristics() const -{ - return props_->get_characteristics(); -} - -//Sets PE characteristics (a value inside header) -void pe_base::set_characteristics(uint16_t ch) -{ - props_->set_characteristics(ch); -} - -//Returns section from RVA -section& pe_base::section_from_rva(uint32_t rva) -{ - //Search for section - for(section_list::iterator i = sections_.begin(); i != sections_.end(); ++i) - { - section& s = *i; - //Return section if found - if(rva >= s.get_virtual_address() && rva < s.get_virtual_address() + s.get_aligned_virtual_size(get_section_alignment())) - return s; - } - - throw pe_exception("No section found by presented address", pe_exception::no_section_found); -} - -//Returns section from RVA -const section& pe_base::section_from_rva(uint32_t rva) const -{ - //Search for section - for(section_list::const_iterator i = sections_.begin(); i != sections_.end(); ++i) - { - const section& s = *i; - //Return section if found - if(rva >= s.get_virtual_address() && rva < s.get_virtual_address() + s.get_aligned_virtual_size(get_section_alignment())) - return s; - } - - throw pe_exception("No section found by presented address", pe_exception::no_section_found); -} - -//Returns section from directory ID -section& pe_base::section_from_directory(uint32_t directory_id) -{ - return section_from_rva(get_directory_rva(directory_id)); -} - -//Returns section from directory ID -const section& pe_base::section_from_directory(uint32_t directory_id) const -{ - return section_from_rva(get_directory_rva(directory_id)); -} - -//Sets section virtual size (actual for the last one of this PE or for unbound section) -void pe_base::set_section_virtual_size(section& s, uint32_t vsize) -{ - //Check if we're changing virtual size of the last section - //Of course, we can change virtual size of section that's not bound to this PE file - if(sections_.empty() || std::find_if(sections_.begin(), sections_.end() - 1, section_ptr_finder(s)) != sections_.end() - 1) - throw pe_exception("Can't change virtual size of any section, except last one", pe_exception::error_changing_section_virtual_size); - - //If we're setting virtual size to zero - if(vsize == 0) - { - //Check if section is empty - if(s.empty()) - throw pe_exception("Cannot set virtual size of empty section to zero", pe_exception::error_changing_section_virtual_size); - - //Set virtual size equal to aligned size of raw data - s.set_virtual_size(s.get_size_of_raw_data()); - } - else - { - s.set_virtual_size(vsize); - } - - //Update image size if we're changing virtual size for the last section of this PE - if(!sections_.empty() || &s == &(*(sections_.end() - 1))) - update_image_size(); -} - -//Expands section raw or virtual size to hold data from specified RVA with specified size -//Section must be free (not bound to any image) -//or the last section of this image -bool pe_base::expand_section(section& s, uint32_t needed_rva, uint32_t needed_size, section_expand_type expand) -{ - //Check if we're changing the last section - //Of course, we can change the section that's not bound to this PE file - if(sections_.empty() || std::find_if(sections_.begin(), sections_.end() - 1, section_ptr_finder(s)) != sections_.end() - 1) - throw pe_exception("Can't expand any section, except last one", pe_exception::error_expanding_section); - - //Check if we should expand our section - if(expand == expand_section_raw && section_data_length_from_rva(s, needed_rva, section_data_raw) < needed_size) - { - //Expand section raw data - s.get_raw_data().resize(needed_rva - s.get_virtual_address() + needed_size); - recalculate_section_sizes(s, false); - return true; - } - else if(expand == expand_section_virtual && section_data_length_from_rva(s, needed_rva, section_data_virtual) < needed_size) - { - //Expand section virtual data - set_section_virtual_size(s, needed_rva - s.get_virtual_address() + needed_size); - return true; - } - - return false; -} - -//Updates image virtual size -void pe_base::update_image_size() -{ - //Write virtual size of image to headers - if(!sections_.empty()) - set_size_of_image(sections_.back().get_virtual_address() + sections_.back().get_aligned_virtual_size(get_section_alignment())); - else - set_size_of_image(get_size_of_headers()); -} - -//Returns checksum of PE file from header -uint32_t pe_base::get_checksum() const -{ - return props_->get_checksum(); -} - -//Sets checksum of PE file -void pe_base::set_checksum(uint32_t checksum) -{ - props_->set_checksum(checksum); -} - -//Returns timestamp of PE file from header -uint32_t pe_base::get_time_date_stamp() const -{ - return props_->get_time_date_stamp(); -} - -//Sets timestamp of PE file -void pe_base::set_time_date_stamp(uint32_t timestamp) -{ - props_->set_time_date_stamp(timestamp); -} - -//Returns Machine field value of PE file from header -uint16_t pe_base::get_machine() const -{ - return props_->get_machine(); -} - -//Sets Machine field value of PE file -void pe_base::set_machine(uint16_t machine) -{ - props_->set_machine(machine); -} - -//Prepares section before attaching it -void pe_base::prepare_section(section& s) -{ - //Calculate its size of raw data - s.set_size_of_raw_data(static_cast<uint32_t>(pe_utils::align_up(s.get_raw_data().length(), get_file_alignment()))); - - //Check section virtual and raw size - if(!s.get_size_of_raw_data() && !s.get_virtual_size()) - throw pe_exception("Virtual and Physical sizes of section can't be 0 at the same time", pe_exception::zero_section_sizes); - - //If section virtual size is zero - if(!s.get_virtual_size()) - { - s.set_virtual_size(s.get_size_of_raw_data()); - } - else - { - //Else calculate its virtual size - s.set_virtual_size( - std::max<uint32_t>(pe_utils::align_up(s.get_size_of_raw_data(), get_file_alignment()), - pe_utils::align_up(s.get_virtual_size(), get_section_alignment()))); - } -} - -//Adds section to image -section& pe_base::add_section(section s) -{ - if(sections_.size() >= maximum_number_of_sections) - throw pe_exception("Maximum number of sections has been reached", pe_exception::no_more_sections_can_be_added); - - //Prepare section before adding it - prepare_section(s); - - //Calculate section virtual address - if(!sections_.empty()) - { - s.set_virtual_address(pe_utils::align_up(sections_.back().get_virtual_address() + sections_.back().get_aligned_virtual_size(get_section_alignment()), get_section_alignment())); - - //We should align last section raw size, if it wasn't aligned - section& last = sections_.back(); - last.set_size_of_raw_data(static_cast<uint32_t>(pe_utils::align_up(last.get_raw_data().length(), get_file_alignment()))); - } - else - { - s.set_virtual_address( - s.get_virtual_address() == 0 - ? pe_utils::align_up(get_size_of_headers(), get_section_alignment()) - : pe_utils::align_up(s.get_virtual_address(), get_section_alignment())); - } - - //Add section to the end of section list - sections_.push_back(s); - //Set number of sections in PE header - set_number_of_sections(static_cast<uint16_t>(sections_.size())); - //Recalculate virtual size of image - set_size_of_image(get_size_of_image() + s.get_aligned_virtual_size(get_section_alignment())); - //Return last section - return sections_.back(); -} - -//Returns true if sectios "s" is already attached to this PE file -bool pe_base::section_attached(const section& s) const -{ - return sections_.end() != std::find_if(sections_.begin(), sections_.end(), section_ptr_finder(s)); -} - -//Returns true if directory exists -bool pe_base::directory_exists(uint32_t id) const -{ - return props_->directory_exists(id); -} - -//Removes directory -void pe_base::remove_directory(uint32_t id) -{ - props_->remove_directory(id); -} - -//Returns directory RVA -uint32_t pe_base::get_directory_rva(uint32_t id) const -{ - return props_->get_directory_rva(id); -} - -//Returns directory size -uint32_t pe_base::get_directory_size(uint32_t id) const -{ - return props_->get_directory_size(id); -} - -//Sets directory RVA (just a value of PE header, no moving occurs) -void pe_base::set_directory_rva(uint32_t id, uint32_t rva) -{ - return props_->set_directory_rva(id, rva); -} - -//Sets directory size (just a value of PE header, no moving occurs) -void pe_base::set_directory_size(uint32_t id, uint32_t size) -{ - return props_->set_directory_size(id, size); -} - -//Strips only zero DATA_DIRECTORY entries to count = min_count -//Returns resulting number of data directories -//strip_iat_directory - if true, even not empty IAT directory will be stripped -uint32_t pe_base::strip_data_directories(uint32_t min_count, bool strip_iat_directory) -{ - return props_->strip_data_directories(min_count, strip_iat_directory); -} - -//Returns true if image has import directory -bool pe_base::has_imports() const -{ - return directory_exists(image_directory_entry_import); -} - -//Returns true if image has export directory -bool pe_base::has_exports() const -{ - return directory_exists(image_directory_entry_export); -} - -//Returns true if image has resource directory -bool pe_base::has_resources() const -{ - return directory_exists(image_directory_entry_resource); -} - -//Returns true if image has security directory -bool pe_base::has_security() const -{ - return directory_exists(image_directory_entry_security); -} - -//Returns true if image has relocations -bool pe_base::has_reloc() const -{ - return directory_exists(image_directory_entry_basereloc) && !(get_characteristics() & image_file_relocs_stripped); -} - -//Returns true if image has TLS directory -bool pe_base::has_tls() const -{ - return directory_exists(image_directory_entry_tls); -} - -//Returns true if image has config directory -bool pe_base::has_config() const -{ - return directory_exists(image_directory_entry_load_config); -} - -//Returns true if image has bound import directory -bool pe_base::has_bound_import() const -{ - return directory_exists(image_directory_entry_bound_import); -} - -//Returns true if image has delay import directory -bool pe_base::has_delay_import() const -{ - return directory_exists(image_directory_entry_delay_import); -} - -//Returns true if image has COM directory -bool pe_base::is_dotnet() const -{ - return directory_exists(image_directory_entry_com_descriptor); -} - -//Returns true if image has exception directory -bool pe_base::has_exception_directory() const -{ - return directory_exists(image_directory_entry_exception); -} - -//Returns true if image has debug directory -bool pe_base::has_debug() const -{ - return directory_exists(image_directory_entry_debug); -} - -//Returns corresponding section data pointer from RVA inside section "s" (checks bounds) -char* pe_base::section_data_from_rva(section& s, uint32_t rva) -{ - //Check if RVA is inside section "s" - if(rva >= s.get_virtual_address() && rva < s.get_virtual_address() + s.get_aligned_virtual_size(get_section_alignment())) - { - if(s.get_raw_data().empty()) - throw pe_exception("Section raw data is empty and cannot be changed", pe_exception::section_is_empty); - - return &s.get_raw_data()[rva - s.get_virtual_address()]; - } - - throw pe_exception("RVA not found inside section", pe_exception::rva_not_exists); -} - -//Returns corresponding section data pointer from RVA inside section "s" (checks bounds) -const char* pe_base::section_data_from_rva(const section& s, uint32_t rva, section_data_type datatype) const -{ - //Check if RVA is inside section "s" - if(rva >= s.get_virtual_address() && rva < s.get_virtual_address() + s.get_aligned_virtual_size(get_section_alignment())) - return (datatype == section_data_raw ? s.get_raw_data().data() : s.get_virtual_data(get_section_alignment()).c_str()) + rva - s.get_virtual_address(); - - throw pe_exception("RVA not found inside section", pe_exception::rva_not_exists); -} - -//Returns section TOTAL RAW/VIRTUAL data length from RVA inside section -uint32_t pe_base::section_data_length_from_rva(uint32_t rva, section_data_type datatype, bool include_headers) const -{ - //if RVA is inside of headers and we're searching them too... - if(include_headers && rva < full_headers_data_.length()) - return static_cast<unsigned long>(full_headers_data_.length()); - - const section& s = section_from_rva(rva); - return static_cast<unsigned long>(datatype == section_data_raw ? s.get_raw_data().length() /* instead of SizeOfRawData */ : s.get_aligned_virtual_size(get_section_alignment())); -} - -//Returns section TOTAL RAW/VIRTUAL data length from VA inside section for PE32 -uint32_t pe_base::section_data_length_from_va(uint32_t va, section_data_type datatype, bool include_headers) const -{ - return section_data_length_from_rva(va_to_rva(va), datatype, include_headers); -} - -//Returns section TOTAL RAW/VIRTUAL data length from VA inside section for PE32/PE64 -uint32_t pe_base::section_data_length_from_va(uint64_t va, section_data_type datatype, bool include_headers) const -{ - return section_data_length_from_rva(va_to_rva(va), datatype, include_headers); -} - -//Returns section remaining RAW/VIRTUAL data length from RVA "rva_inside" to the end of section containing RVA "rva" -uint32_t pe_base::section_data_length_from_rva(uint32_t rva, uint32_t rva_inside, section_data_type datatype, bool include_headers) const -{ - //if RVAs are inside of headers and we're searching them too... - if(include_headers && rva < full_headers_data_.length() && rva_inside < full_headers_data_.length()) - return static_cast<unsigned long>(full_headers_data_.length() - rva_inside); - - const section& s = section_from_rva(rva); - if(rva_inside < s.get_virtual_address()) - throw pe_exception("RVA not found inside section", pe_exception::rva_not_exists); - - //Calculate remaining length of section data from "rva" address - long length = static_cast<long>(datatype == section_data_raw ? s.get_raw_data().length() /* instead of SizeOfRawData */ : s.get_aligned_virtual_size(get_section_alignment())) - + s.get_virtual_address() - rva_inside; - - if(length < 0) - return 0; - - return static_cast<unsigned long>(length); -} - -//Returns section remaining RAW/VIRTUAL data length from VA "va_inside" to the end of section containing VA "va" for PE32 -uint32_t pe_base::section_data_length_from_va(uint32_t va, uint32_t va_inside, section_data_type datatype, bool include_headers) const -{ - return section_data_length_from_rva(va_to_rva(va), va_to_rva(va_inside), datatype, include_headers); -} - -//Returns section remaining RAW/VIRTUAL data length from VA "va_inside" to the end of section containing VA "va" for PE32/PE64 -uint32_t pe_base::section_data_length_from_va(uint64_t va, uint64_t va_inside, section_data_type datatype, bool include_headers) const -{ - return section_data_length_from_rva(va_to_rva(va), va_to_rva(va_inside), datatype, include_headers); -} - -//Returns section remaining RAW/VIRTUAL data length from RVA to the end of section "s" (checks bounds) -uint32_t pe_base::section_data_length_from_rva(const section& s, uint32_t rva_inside, section_data_type datatype) const -{ - //Check rva_inside - if(rva_inside >= s.get_virtual_address() && rva_inside < s.get_virtual_address() + s.get_aligned_virtual_size(get_section_alignment())) - { - //Calculate remaining length of section data from "rva" address - int32_t length = static_cast<int32_t>(datatype == section_data_raw ? s.get_raw_data().length() /* instead of SizeOfRawData */ : s.get_aligned_virtual_size(get_section_alignment())) - + s.get_virtual_address() - rva_inside; - - if(length < 0) - return 0; - - return static_cast<uint32_t>(length); - } - - throw pe_exception("RVA not found inside section", pe_exception::rva_not_exists); -} - -//Returns section remaining RAW/VIRTUAL data length from VA to the end of section "s" for PE32 (checks bounds) -uint32_t pe_base::section_data_length_from_va(const section& s, uint32_t va_inside, section_data_type datatype) const -{ - return section_data_length_from_rva(s, va_to_rva(va_inside), datatype); -} - -//Returns section remaining RAW/VIRTUAL data length from VA to the end of section "s" for PE32/PE64 (checks bounds) -uint32_t pe_base::section_data_length_from_va(const section& s, uint64_t va_inside, section_data_type datatype) const -{ - return section_data_length_from_rva(s, va_to_rva(va_inside), datatype); -} - -//Returns corresponding section data pointer from RVA inside section -char* pe_base::section_data_from_rva(uint32_t rva, bool include_headers) -{ - //if RVA is inside of headers and we're searching them too... - if(include_headers && rva < full_headers_data_.length()) - return &full_headers_data_[rva]; - - section& s = section_from_rva(rva); - - if(s.get_raw_data().empty()) - throw pe_exception("Section raw data is empty and cannot be changed", pe_exception::section_is_empty); - - return &s.get_raw_data()[rva - s.get_virtual_address()]; -} - -//Returns corresponding section data pointer from RVA inside section -const char* pe_base::section_data_from_rva(uint32_t rva, section_data_type datatype, bool include_headers) const -{ - //if RVA is inside of headers and we're searching them too... - if(include_headers && rva < full_headers_data_.length()) - return &full_headers_data_[rva]; - - const section& s = section_from_rva(rva); - return (datatype == section_data_raw ? s.get_raw_data().data() : s.get_virtual_data(get_section_alignment()).c_str()) + rva - s.get_virtual_address(); -} - -//Reads DOS headers from istream -void pe_base::read_dos_header(std::istream& file, image_dos_header& header) -{ - //Check istream flags - if(file.bad() || file.eof()) - throw pe_exception("PE file stream is bad or closed.", pe_exception::bad_pe_file); - - //Read DOS header and check istream - file.read(reinterpret_cast<char*>(&header), sizeof(image_dos_header)); - if(file.bad() || file.eof()) - throw pe_exception("Unable to read IMAGE_DOS_HEADER", pe_exception::bad_dos_header); - - //Check DOS header magic - if(header.e_magic != 0x5a4d) //"MZ" - throw pe_exception("IMAGE_DOS_HEADER signature is incorrect", pe_exception::bad_dos_header); -} - -//Reads DOS headers from istream -void pe_base::read_dos_header(std::istream& file) -{ - read_dos_header(file, dos_header_); -} - -//Reads PE image from istream -void pe_base::read_pe(std::istream& file, bool read_debug_raw_data) -{ - //Get istream size - std::streamoff filesize = pe_utils::get_file_size(file); - - //Check if PE header is DWORD-aligned - if((dos_header_.e_lfanew % sizeof(uint32_t)) != 0) - throw pe_exception("PE header is not DWORD-aligned", pe_exception::bad_dos_header); - - //Seek to NT headers - file.seekg(dos_header_.e_lfanew); - if(file.bad() || file.fail()) - throw pe_exception("Cannot reach IMAGE_NT_HEADERS", pe_exception::image_nt_headers_not_found); - - //Read NT headers - file.read(get_nt_headers_ptr(), get_sizeof_nt_header() - sizeof(image_data_directory) * image_numberof_directory_entries); - if(file.bad() || file.eof()) - throw pe_exception("Error reading IMAGE_NT_HEADERS", pe_exception::error_reading_image_nt_headers); - - //Check PE signature - if(get_pe_signature() != 0x4550) //"PE" - throw pe_exception("Incorrect PE signature", pe_exception::pe_signature_incorrect); - - //Check number of directories - if(get_number_of_rvas_and_sizes() > image_numberof_directory_entries) - set_number_of_rvas_and_sizes(image_numberof_directory_entries); - - if(get_number_of_rvas_and_sizes() > 0) - { - //Read data directory headers, if any - file.read(get_nt_headers_ptr() + (get_sizeof_nt_header() - sizeof(image_data_directory) * image_numberof_directory_entries), sizeof(image_data_directory) * get_number_of_rvas_and_sizes()); - if(file.bad() || file.eof()) - throw pe_exception("Error reading DATA_DIRECTORY headers", pe_exception::error_reading_data_directories); - } - - //Check section number - //Images with zero section number accepted - if(get_number_of_sections() > maximum_number_of_sections) - throw pe_exception("Incorrect number of sections", pe_exception::section_number_incorrect); - - //Check PE magic - if(get_magic() != get_needed_magic()) - throw pe_exception("Incorrect PE signature", pe_exception::pe_signature_incorrect); - - //Check section alignment - if(!pe_utils::is_power_of_2(get_section_alignment())) - throw pe_exception("Incorrect section alignment", pe_exception::incorrect_section_alignment); - - //Check file alignment - if(!pe_utils::is_power_of_2(get_file_alignment())) - throw pe_exception("Incorrect file alignment", pe_exception::incorrect_file_alignment); - - if(get_file_alignment() != get_section_alignment() && (get_file_alignment() < minimum_file_alignment || get_file_alignment() > get_section_alignment())) - throw pe_exception("Incorrect file alignment", pe_exception::incorrect_file_alignment); - - //Check size of image - if(pe_utils::align_up(get_size_of_image(), get_section_alignment()) == 0) - throw pe_exception("Incorrect size of image", pe_exception::incorrect_size_of_image); - - //Read rich data overlay / DOS stub (if any) - if(static_cast<uint32_t>(dos_header_.e_lfanew) > sizeof(image_dos_header)) - { - rich_overlay_.resize(dos_header_.e_lfanew - sizeof(image_dos_header)); - file.seekg(sizeof(image_dos_header)); - file.read(&rich_overlay_[0], dos_header_.e_lfanew - sizeof(image_dos_header)); - if(file.bad() || file.eof()) - throw pe_exception("Error reading 'Rich' & 'DOS stub' overlay", pe_exception::error_reading_overlay); - } - - //Calculate first section raw position - //Sum is safe here - uint32_t first_section = dos_header_.e_lfanew + get_size_of_optional_header() + sizeof(image_file_header) + sizeof(uint32_t) /* Signature */; - - if(get_number_of_sections() > 0) - { - //Go to first section - file.seekg(first_section); - if(file.bad() || file.fail()) - throw pe_exception("Cannot reach section headers", pe_exception::image_section_headers_not_found); - } - - uint32_t last_raw_size = 0; - - //Read all sections - for(int i = 0; i < get_number_of_sections(); i++) - { - section s; - //Read section header - file.read(reinterpret_cast<char*>(&s.get_raw_header()), sizeof(image_section_header)); - if(file.bad() || file.eof()) - throw pe_exception("Error reading section header", pe_exception::error_reading_section_header); - - //Save next section header position - std::streamoff next_sect = file.tellg(); - - //Check section virtual and raw sizes - if(!s.get_size_of_raw_data() && !s.get_virtual_size()) - throw pe_exception("Virtual and Physical sizes of section can't be 0 at the same time", pe_exception::zero_section_sizes); - - //Check for adequate values of section fields - if(!pe_utils::is_sum_safe(s.get_virtual_address(), s.get_virtual_size()) || s.get_virtual_size() > pe_utils::two_gb - || !pe_utils::is_sum_safe(s.get_pointer_to_raw_data(), s.get_size_of_raw_data()) || s.get_size_of_raw_data() > pe_utils::two_gb) - throw pe_exception("Incorrect section address or size", pe_exception::section_incorrect_addr_or_size); - - if(s.get_size_of_raw_data() != 0) - { - //If section has raw data - - //If section raw data size is greater than virtual, fix it - last_raw_size = s.get_size_of_raw_data(); - if(pe_utils::align_up(s.get_size_of_raw_data(), get_file_alignment()) > pe_utils::align_up(s.get_virtual_size(), get_section_alignment())) - s.set_size_of_raw_data(s.get_virtual_size()); - - //Check virtual and raw section sizes and addresses - if(s.get_virtual_address() + pe_utils::align_up(s.get_virtual_size(), get_section_alignment()) > pe_utils::align_up(get_size_of_image(), get_section_alignment()) - || - pe_utils::align_down(s.get_pointer_to_raw_data(), get_file_alignment()) + s.get_size_of_raw_data() > static_cast<uint32_t>(filesize)) - throw pe_exception("Incorrect section address or size", pe_exception::section_incorrect_addr_or_size); - - //Seek to section raw data - file.seekg(pe_utils::align_down(s.get_pointer_to_raw_data(), get_file_alignment())); - if(file.bad() || file.fail()) - throw pe_exception("Cannot reach section data", pe_exception::image_section_data_not_found); - - //Read section raw data - s.get_raw_data().resize(s.get_size_of_raw_data()); - file.read(&s.get_raw_data()[0], s.get_size_of_raw_data()); - if(file.bad() || file.fail()) - throw pe_exception("Error reading section data", pe_exception::image_section_data_not_found); - } - - //Check virtual address and size of section - if(s.get_virtual_address() + s.get_aligned_virtual_size(get_section_alignment()) > pe_utils::align_up(get_size_of_image(), get_section_alignment())) - throw pe_exception("Incorrect section address or size", pe_exception::section_incorrect_addr_or_size); - - //Save section - sections_.push_back(s); - - //Seek to the next section header - file.seekg(next_sect); - } - - //Check size of headers: SizeOfHeaders can't be larger than first section VA - if(!sections_.empty() && get_size_of_headers() > sections_.front().get_virtual_address()) - throw pe_exception("Incorrect size of headers", pe_exception::incorrect_size_of_headers); - - //If image has more than two sections - if(sections_.size() >= 2) - { - //Check sections virtual sizes - for(section_list::const_iterator i = sections_.begin() + 1; i != sections_.end(); ++i) - { - if((*i).get_virtual_address() != (*(i - 1)).get_virtual_address() + (*(i - 1)).get_aligned_virtual_size(get_section_alignment())) - throw pe_exception("Section table is incorrect", pe_exception::image_section_table_incorrect); - } - } - - //Check if image has overlay in the end of file - has_overlay_ = !sections_.empty() && filesize > static_cast<std::streamoff>(sections_.back().get_pointer_to_raw_data() + last_raw_size); - - { - //Additionally, read data from the beginning of istream to size of headers - file.seekg(0); - uint32_t size_of_headers = std::min<uint32_t>(get_size_of_headers(), static_cast<uint32_t>(filesize)); - - if(!sections_.empty()) - { - for(section_list::const_iterator i = sections_.begin(); i != sections_.end(); ++i) - { - if(!(*i).empty()) - { - size_of_headers = std::min<uint32_t>(get_size_of_headers(), (*i).get_pointer_to_raw_data()); - break; - } - } - } - - full_headers_data_.resize(size_of_headers); - file.read(&full_headers_data_[0], size_of_headers); - if(file.bad() || file.eof()) - throw pe_exception("Error reading file", pe_exception::error_reading_file); - } - - //Moreover, if there's debug directory, read its raw data for some debug info types - while(read_debug_raw_data && has_debug()) - { - try - { - //Check the length in bytes of the section containing debug directory - if(section_data_length_from_rva(get_directory_rva(image_directory_entry_debug), get_directory_rva(image_directory_entry_debug), section_data_virtual, true) < sizeof(image_debug_directory)) - break; - - unsigned long current_pos = get_directory_rva(image_directory_entry_debug); - - //First IMAGE_DEBUG_DIRECTORY table - image_debug_directory directory = section_data_from_rva<image_debug_directory>(current_pos, section_data_virtual, true); - - //Iterate over all IMAGE_DEBUG_DIRECTORY directories - while(directory.PointerToRawData - && current_pos < get_directory_rva(image_directory_entry_debug) + get_directory_size(image_directory_entry_debug)) - { - //If we have something to read - if((directory.Type == image_debug_type_codeview - || directory.Type == image_debug_type_misc - || directory.Type == image_debug_type_coff) - && directory.SizeOfData) - { - std::string data; - data.resize(directory.SizeOfData); - file.seekg(directory.PointerToRawData); - file.read(&data[0], directory.SizeOfData); - if(file.bad() || file.eof()) - throw pe_exception("Error reading file", pe_exception::error_reading_file); - - debug_data_.insert(std::make_pair(directory.PointerToRawData, data)); - } - - //Go to next debug entry - current_pos += sizeof(image_debug_directory); - directory = section_data_from_rva<image_debug_directory>(current_pos, section_data_virtual, true); - } - - break; - } - catch(const pe_exception&) - { - //Don't throw any exception here, if debug info is corrupted or incorrect - break; - } - catch(const std::bad_alloc&) - { - //Don't throw any exception here, if debug info is corrupted or incorrect - break; - } - } -} - -//Returns PE type of this image -pe_type pe_base::get_pe_type() const -{ - return props_->get_pe_type(); -} - -//Returns PE type (PE or PE+) from pe_type enumeration (minimal correctness checks) -pe_type pe_base::get_pe_type(std::istream& file) -{ - //Save state of the istream - std::ios_base::iostate state = file.exceptions(); - std::streamoff old_offset = file.tellg(); - image_nt_headers32 nt_headers; - image_dos_header header; - - try - { - //Read dos header - file.exceptions(std::ios::goodbit); - read_dos_header(file, header); - - //Seek to the NT headers start - file.seekg(header.e_lfanew); - if(file.bad() || file.fail()) - throw pe_exception("Cannot reach IMAGE_NT_HEADERS", pe_exception::image_nt_headers_not_found); - - //Read NT headers (we're using 32-bit version, because there's no significant differencies between 32 and 64 bit version structures) - file.read(reinterpret_cast<char*>(&nt_headers), sizeof(image_nt_headers32) - sizeof(image_data_directory) * image_numberof_directory_entries); - if(file.bad() || file.eof()) - throw pe_exception("Error reading IMAGE_NT_HEADERS", pe_exception::error_reading_image_nt_headers); - - //Check NT headers signature - if(nt_headers.Signature != 0x4550) //"PE" - throw pe_exception("Incorrect PE signature", pe_exception::pe_signature_incorrect); - - //Check NT headers magic - if(nt_headers.OptionalHeader.Magic != image_nt_optional_hdr32_magic && nt_headers.OptionalHeader.Magic != image_nt_optional_hdr64_magic) - throw pe_exception("Incorrect PE signature", pe_exception::pe_signature_incorrect); - } - catch(const std::exception&) - { - //If something went wrong, restore istream state - file.exceptions(state); - file.seekg(old_offset); - file.clear(); - //Retrhow exception - throw; - } - - //Restore stream state - file.exceptions(state); - file.seekg(old_offset); - file.clear(); - - //Determine PE type and return it - return nt_headers.OptionalHeader.Magic == image_nt_optional_hdr64_magic ? pe_type_64 : pe_type_32; -} - -//Returns true if image has overlay data at the end of file -bool pe_base::has_overlay() const -{ - return has_overlay_; -} - -//Clears PE characteristics flag -void pe_base::clear_characteristics_flags(uint16_t flags) -{ - set_characteristics(get_characteristics() & ~flags); -} - -//Sets PE characteristics flag -void pe_base::set_characteristics_flags(uint16_t flags) -{ - set_characteristics(get_characteristics() | flags); -} - -//Returns true if PE characteristics flag set -bool pe_base::check_characteristics_flag(uint16_t flag) const -{ - return (get_characteristics() & flag) ? true : false; -} - -//Returns subsystem value -uint16_t pe_base::get_subsystem() const -{ - return props_->get_subsystem(); -} - -//Sets subsystem value -void pe_base::set_subsystem(uint16_t subsystem) -{ - props_->set_subsystem(subsystem); -} - -//Returns true if image has console subsystem -bool pe_base::is_console() const -{ - return get_subsystem() == image_subsystem_windows_cui; -} - -//Returns true if image has Windows GUI subsystem -bool pe_base::is_gui() const -{ - return get_subsystem() == image_subsystem_windows_gui; -} - -//Sets required operation system version -void pe_base::set_os_version(uint16_t major, uint16_t minor) -{ - props_->set_os_version(major, minor); -} - -//Returns required operation system version (minor word) -uint16_t pe_base::get_minor_os_version() const -{ - return props_->get_minor_os_version(); -} - -//Returns required operation system version (major word) -uint16_t pe_base::get_major_os_version() const -{ - return props_->get_major_os_version(); -} - -//Sets required subsystem version -void pe_base::set_subsystem_version(uint16_t major, uint16_t minor) -{ - props_->set_subsystem_version(major, minor); -} - -//Returns required subsystem version (minor word) -uint16_t pe_base::get_minor_subsystem_version() const -{ - return props_->get_minor_subsystem_version(); -} - -//Returns required subsystem version (major word) -uint16_t pe_base::get_major_subsystem_version() const -{ - return props_->get_major_subsystem_version(); -} - -//Returns corresponding section data pointer from VA inside section "s" for PE32 (checks bounds) -char* pe_base::section_data_from_va(section& s, uint32_t va) //Always returns raw data -{ - return section_data_from_rva(s, va_to_rva(va)); -} - -//Returns corresponding section data pointer from VA inside section "s" for PE32 (checks bounds) -const char* pe_base::section_data_from_va(const section& s, uint32_t va, section_data_type datatype) const -{ - return section_data_from_rva(s, va_to_rva(va), datatype); -} - -//Returns corresponding section data pointer from VA inside section for PE32 -char* pe_base::section_data_from_va(uint32_t va, bool include_headers) //Always returns raw data -{ - return section_data_from_rva(va_to_rva(va), include_headers); -} - -//Returns corresponding section data pointer from VA inside section for PE32 -const char* pe_base::section_data_from_va(uint32_t va, section_data_type datatype, bool include_headers) const -{ - return section_data_from_rva(va_to_rva(va), datatype, include_headers); -} - -//Returns corresponding section data pointer from VA inside section "s" for PE32/PE64 (checks bounds) -char* pe_base::section_data_from_va(section& s, uint64_t va) //Always returns raw data -{ - return section_data_from_rva(s, va_to_rva(va)); -} - -//Returns corresponding section data pointer from VA inside section "s" for PE32/PE64 (checks bounds) -const char* pe_base::section_data_from_va(const section& s, uint64_t va, section_data_type datatype) const -{ - return section_data_from_rva(s, va_to_rva(va), datatype); -} - -//Returns corresponding section data pointer from VA inside section for PE32/PE64 -char* pe_base::section_data_from_va(uint64_t va, bool include_headers) //Always returns raw data -{ - return section_data_from_rva(va_to_rva(va), include_headers); -} - -//Returns corresponding section data pointer from VA inside section for PE32/PE64 -const char* pe_base::section_data_from_va(uint64_t va, section_data_type datatype, bool include_headers) const -{ - return section_data_from_rva(va_to_rva(va), datatype, include_headers); -} - -//Returns section from VA inside it for PE32 -section& pe_base::section_from_va(uint32_t va) -{ - return section_from_rva(va_to_rva(va)); -} - -//Returns section from VA inside it for PE32/PE64 -section& pe_base::section_from_va(uint64_t va) -{ - return section_from_rva(va_to_rva(va)); -} - -//Returns section from RVA inside it for PE32 -const section& pe_base::section_from_va(uint32_t va) const -{ - return section_from_rva(va_to_rva(va)); -} - -//Returns section from RVA inside it for PE32/PE64 -const section& pe_base::section_from_va(uint64_t va) const -{ - return section_from_rva(va_to_rva(va)); -} - -uint32_t pe_base::va_to_rva(uint32_t va, bool bound_check) const -{ - return props_->va_to_rva(va, bound_check); -} - -uint32_t pe_base::va_to_rva(uint64_t va, bool bound_check) const -{ - return props_->va_to_rva(va, bound_check); -} - -uint32_t pe_base::rva_to_va_32(uint32_t rva) const -{ - return props_->rva_to_va_32(rva); -} - -uint64_t pe_base::rva_to_va_64(uint32_t rva) const -{ - return props_->rva_to_va_64(rva); -} - -//Relative Virtual Address (RVA) to Virtual Address (VA) convertion for PE32 -void pe_base::rva_to_va(uint32_t rva, uint32_t& va) const -{ - va = rva_to_va_32(rva); -} - -//Relative Virtual Address (RVA) to Virtual Address (VA) convertions for PE32/PE64 -void pe_base::rva_to_va(uint32_t rva, uint64_t& va) const -{ - va = rva_to_va_64(rva); -} - -//Returns section from file offset (4gb max) -section& pe_base::section_from_file_offset(uint32_t offset) -{ - return *file_offset_to_section(offset); -} - -//Returns section from file offset (4gb max) -const section& pe_base::section_from_file_offset(uint32_t offset) const -{ - return *file_offset_to_section(offset); -} - -//Returns section and offset (raw data only) from its start from RVA -const std::pair<uint32_t, const section*> pe_base::section_and_offset_from_rva(uint32_t rva) const -{ - const section& s = section_from_rva(rva); - return std::make_pair(rva - s.get_virtual_address(), &s); -} - -//Returns DLL Characteristics -uint16_t pe_base::get_dll_characteristics() const -{ - return props_->get_dll_characteristics(); -} - -//Sets DLL Characteristics -void pe_base::set_dll_characteristics(uint16_t characteristics) -{ - props_->set_dll_characteristics(characteristics); -} - -//Returns size of headers -uint32_t pe_base::get_size_of_headers() const -{ - return props_->get_size_of_headers(); -} - -//Returns size of optional header -uint16_t pe_base::get_size_of_optional_header() const -{ - return props_->get_size_of_optional_header(); -} - -//Returns PE signature -uint32_t pe_base::get_pe_signature() const -{ - return props_->get_pe_signature(); -} - -//Returns magic value -uint32_t pe_base::get_magic() const -{ - return props_->get_magic(); -} - -//Returns image base for PE32 -void pe_base::get_image_base(uint32_t& base) const -{ - base = get_image_base_32(); -} - -//Returns image base for PE32 and PE64 respectively -uint32_t pe_base::get_image_base_32() const -{ - return props_->get_image_base_32(); -} - -//Sets image base for PE32 and PE64 respectively -uint64_t pe_base::get_image_base_64() const -{ - return props_->get_image_base_64(); -} - -//RVA to RAW file offset convertion (4gb max) -uint32_t pe_base::rva_to_file_offset(uint32_t rva) const -{ - //Maybe, RVA is inside PE headers - if(rva < get_size_of_headers()) - return rva; - - const section& s = section_from_rva(rva); - return s.get_pointer_to_raw_data() + rva - s.get_virtual_address(); -} - -//RAW file offset to RVA convertion (4gb max) -uint32_t pe_base::file_offset_to_rva(uint32_t offset) const -{ - //Maybe, offset is inside PE headers - if(offset < get_size_of_headers()) - return offset; - - const section_list::const_iterator it = file_offset_to_section(offset); - return offset - (*it).get_pointer_to_raw_data() + (*it).get_virtual_address(); -} - -//RAW file offset to section convertion helper (4gb max) -section_list::const_iterator pe_base::file_offset_to_section(uint32_t offset) const -{ - section_list::const_iterator it = std::find_if(sections_.begin(), sections_.end(), section_by_raw_offset(offset)); - if(it == sections_.end()) - throw pe_exception("No section found by presented file offset", pe_exception::no_section_found); - - return it; -} - -//RAW file offset to section convertion helper (4gb max) -section_list::iterator pe_base::file_offset_to_section(uint32_t offset) -{ - section_list::iterator it = std::find_if(sections_.begin(), sections_.end(), section_by_raw_offset(offset)); - if(it == sections_.end()) - throw pe_exception("No section found by presented file offset", pe_exception::no_section_found); - - return it; -} - -//RVA from section raw data offset -uint32_t pe_base::rva_from_section_offset(const section& s, uint32_t raw_offset_from_section_start) -{ - return s.get_virtual_address() + raw_offset_from_section_start; -} - -//Returns image base for PE32/PE64 -void pe_base::get_image_base(uint64_t& base) const -{ - base = get_image_base_64(); -} - -//Sets new image base -void pe_base::set_image_base(uint32_t base) -{ - props_->set_image_base(base); -} - -void pe_base::set_image_base_64(uint64_t base) -{ - props_->set_image_base_64(base); -} - -//Sets heap size commit for PE32 and PE64 respectively -void pe_base::set_heap_size_commit(uint32_t size) -{ - props_->set_heap_size_commit(size); -} - -void pe_base::set_heap_size_commit(uint64_t size) -{ - props_->set_heap_size_commit(size); -} - -//Sets heap size reserve for PE32 and PE64 respectively -void pe_base::set_heap_size_reserve(uint32_t size) -{ - props_->set_heap_size_reserve(size); -} - -void pe_base::set_heap_size_reserve(uint64_t size) -{ - props_->set_heap_size_reserve(size); -} - -//Sets stack size commit for PE32 and PE64 respectively -void pe_base::set_stack_size_commit(uint32_t size) -{ - props_->set_stack_size_commit(size); -} - -void pe_base::set_stack_size_commit(uint64_t size) -{ - props_->set_stack_size_commit(size); -} - -//Sets stack size reserve for PE32 and PE64 respectively -void pe_base::set_stack_size_reserve(uint32_t size) -{ - props_->set_stack_size_reserve(size); -} - -void pe_base::set_stack_size_reserve(uint64_t size) -{ - props_->set_stack_size_reserve(size); -} - -//Returns heap size commit for PE32 and PE64 respectively -uint32_t pe_base::get_heap_size_commit_32() const -{ - return props_->get_heap_size_commit_32(); -} - -uint64_t pe_base::get_heap_size_commit_64() const -{ - return props_->get_heap_size_commit_64(); -} - -//Returns heap size reserve for PE32 and PE64 respectively -uint32_t pe_base::get_heap_size_reserve_32() const -{ - return props_->get_heap_size_reserve_32(); -} - -uint64_t pe_base::get_heap_size_reserve_64() const -{ - return props_->get_heap_size_reserve_64(); -} - -//Returns stack size commit for PE32 and PE64 respectively -uint32_t pe_base::get_stack_size_commit_32() const -{ - return props_->get_stack_size_commit_32(); -} - -uint64_t pe_base::get_stack_size_commit_64() const -{ - return props_->get_stack_size_commit_64(); -} - -//Returns stack size reserve for PE32 and PE64 respectively -uint32_t pe_base::get_stack_size_reserve_32() const -{ - return props_->get_stack_size_reserve_32(); -} - -uint64_t pe_base::get_stack_size_reserve_64() const -{ - return props_->get_stack_size_reserve_64(); -} - -//Returns heap size commit for PE32 -void pe_base::get_heap_size_commit(uint32_t& size) const -{ - size = get_heap_size_commit_32(); -} - -//Returns heap size commit for PE32/PE64 -void pe_base::get_heap_size_commit(uint64_t& size) const -{ - size = get_heap_size_commit_64(); -} - -//Returns heap size reserve for PE32 -void pe_base::get_heap_size_reserve(uint32_t& size) const -{ - size = get_heap_size_reserve_32(); -} - -//Returns heap size reserve for PE32/PE64 -void pe_base::get_heap_size_reserve(uint64_t& size) const -{ - size = get_heap_size_reserve_64(); -} - -//Returns stack size commit for PE32 -void pe_base::get_stack_size_commit(uint32_t& size) const -{ - size = get_stack_size_commit_32(); -} - -//Returns stack size commit for PE32/PE64 -void pe_base::get_stack_size_commit(uint64_t& size) const -{ - size = get_stack_size_commit_64(); -} - -//Returns stack size reserve for PE32 -void pe_base::get_stack_size_reserve(uint32_t& size) const -{ - size = get_stack_size_reserve_32(); -} - -//Returns stack size reserve for PE32/PE64 -void pe_base::get_stack_size_reserve(uint64_t& size) const -{ - size = get_stack_size_reserve_64(); -} - -//Realigns file (changes file alignment) -void pe_base::realign_file(uint32_t new_file_alignment) -{ - //Checks alignment for correctness - set_file_alignment(new_file_alignment); - realign_all_sections(); -} - -//Helper function to recalculate RAW and virtual section sizes and strip it, if necessary -void pe_base::recalculate_section_sizes(section& s, bool auto_strip) -{ - prepare_section(s); //Recalculate section raw addresses - - //Strip RAW size of section, if it is the last one - //For all others it must be file-aligned and calculated by prepare_section() call - if(auto_strip && !(sections_.empty() || &s == &*(sections_.end() - 1))) - { - //Strip ending raw data nullbytes to optimize size - std::string& raw_data = s.get_raw_data(); - if(!raw_data.empty()) - { - std::string::size_type i = raw_data.length(); - for(; i != 1; --i) - { - if(raw_data[i - 1] != 0) - break; - } - - raw_data.resize(i); - } - - s.set_size_of_raw_data(static_cast<uint32_t>(raw_data.length())); - } - - //Can occur only for last section - if(pe_utils::align_up(s.get_virtual_size(), get_section_alignment()) < pe_utils::align_up(s.get_size_of_raw_data(), get_file_alignment())) - set_section_virtual_size(s, pe_utils::align_up(s.get_size_of_raw_data(), get_section_alignment())); //Recalculate section virtual size -} - -//Returns data from the beginning of image -//Size = SizeOfHeaders -const std::string& pe_base::get_full_headers_data() const -{ - return full_headers_data_; -} - -const pe_base::debug_data_list& pe_base::get_raw_debug_data_list() const -{ - return debug_data_; -} - -//Sets number of sections -void pe_base::set_number_of_sections(uint16_t number) -{ - props_->set_number_of_sections(number); -} - -//Sets size of image -void pe_base::set_size_of_image(uint32_t size) -{ - props_->set_size_of_image(size); -} - -//Sets size of headers -void pe_base::set_size_of_headers(uint32_t size) -{ - props_->set_size_of_headers(size); -} - -//Sets size of optional headers -void pe_base::set_size_of_optional_header(uint16_t size) -{ - props_->set_size_of_optional_header(size); -} - -//Returns nt headers data pointer -char* pe_base::get_nt_headers_ptr() -{ - return props_->get_nt_headers_ptr(); -} - -//Returns nt headers data pointer -const char* pe_base::get_nt_headers_ptr() const -{ - return props_->get_nt_headers_ptr(); -} - -//Returns sizeof() nt headers -uint32_t pe_base::get_sizeof_nt_header() const -{ - return props_->get_sizeof_nt_header(); -} - -//Returns sizeof() optional headers -uint32_t pe_base::get_sizeof_opt_headers() const -{ - return props_->get_sizeof_opt_headers(); -} - -//Sets file alignment (no checks) -void pe_base::set_file_alignment_unchecked(uint32_t alignment) -{ - props_->set_file_alignment_unchecked(alignment); -} - -//Sets base of code -void pe_base::set_base_of_code(uint32_t base) -{ - props_->set_base_of_code(base); -} - -//Returns base of code -uint32_t pe_base::get_base_of_code() const -{ - return props_->get_base_of_code(); -} - -//Returns needed magic of image -uint32_t pe_base::get_needed_magic() const -{ - return props_->get_needed_magic(); -} -} diff --git a/tools/pe_bliss/pe_base.h b/tools/pe_bliss/pe_base.h deleted file mode 100644 index b5416cf1e2..0000000000 --- a/tools/pe_bliss/pe_base.h +++ /dev/null @@ -1,544 +0,0 @@ -/*************************************************************************/ -/* Copyright (c) 2015 dx, http://kaimi.ru */ -/* */ -/* Permission is hereby granted, free of charge, to any person */ -/* obtaining a copy of this software and associated documentation */ -/* files (the "Software"), to deal in the Software without */ -/* restriction, including without limitation the rights to use, */ -/* copy, modify, merge, publish, distribute, sublicense, and/or */ -/* sell copies of the Software, and to permit persons to whom the */ -/* Software is furnished to do so, subject to the following conditions: */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#pragma once -#include <string> -#include <vector> -#include <istream> -#include <ostream> -#include <map> -#include "pe_exception.h" -#include "pe_structures.h" -#include "utils.h" -#include "pe_section.h" -#include "pe_properties.h" - -//Please don't remove this information from header -//PEBliss 1.0.0 -//(c) DX 2011 - 2012, http://kaimi.ru -//Free to use for commertial and non-commertial purposes, modification and distribution - -// == more important == -//TODO: compact import rebuilder -//TODO: remove sections in the middle -//== less important == -//TODO: relocations that take more than one element (seems to be not possible in Windows PE, but anyway) -//TODO: delay import directory -//TODO: write message tables -//TODO: write string tables -//TODO: read security information -//TODO: read full .NET information - -namespace pe_bliss -{ -//Portable executable class -class pe_base -{ -public: //CONSTRUCTORS - //Constructor from stream - pe_base(std::istream& file, const pe_properties& props, bool read_debug_raw_data = true); - - //Constructor of empty PE-file - explicit pe_base(const pe_properties& props, uint32_t section_alignment = 0x1000, bool dll = false, uint16_t subsystem = pe_win::image_subsystem_windows_gui); - - pe_base(const pe_base& pe); - pe_base& operator=(const pe_base& pe); - -public: - ~pe_base(); - -public: //STUB - //Strips stub MSVS overlay, if any - void strip_stub_overlay(); - //Fills stub MSVS overlay with specified byte - void fill_stub_overlay(char c); - //Sets stub MSVS overlay - void set_stub_overlay(const std::string& data); - //Returns stub overlay contents - const std::string& get_stub_overlay() const; - - -public: //DIRECTORIES - //Returns true if directory exists - bool directory_exists(uint32_t id) const; - //Removes directory - void remove_directory(uint32_t id); - - //Returns directory RVA - uint32_t get_directory_rva(uint32_t id) const; - //Returns directory size - uint32_t get_directory_size(uint32_t id) const; - - //Sets directory RVA (just a value of PE header, no moving occurs) - void set_directory_rva(uint32_t id, uint32_t rva); - //Sets directory size (just a value of PE header, no moving occurs) - void set_directory_size(uint32_t id, uint32_t size); - - //Strips only zero DATA_DIRECTORY entries to count = min_count - //Returns resulting number of data directories - //strip_iat_directory - if true, even not empty IAT directory will be stripped - uint32_t strip_data_directories(uint32_t min_count = 1, bool strip_iat_directory = true); - - //Returns true if image has import directory - bool has_imports() const; - //Returns true if image has export directory - bool has_exports() const; - //Returns true if image has resource directory - bool has_resources() const; - //Returns true if image has security directory - bool has_security() const; - //Returns true if image has relocations - bool has_reloc() const; - //Returns true if image has TLS directory - bool has_tls() const; - //Returns true if image has config directory - bool has_config() const; - //Returns true if image has bound import directory - bool has_bound_import() const; - //Returns true if image has delay import directory - bool has_delay_import() const; - //Returns true if image has COM directory - bool is_dotnet() const; - //Returns true if image has exception directory - bool has_exception_directory() const; - //Returns true if image has debug directory - bool has_debug() const; - - //Returns subsystem value - uint16_t get_subsystem() const; - //Sets subsystem value - void set_subsystem(uint16_t subsystem); - //Returns true if image has console subsystem - bool is_console() const; - //Returns true if image has Windows GUI subsystem - bool is_gui() const; - - //Sets required operation system version - void set_os_version(uint16_t major, uint16_t minor); - //Returns required operation system version (minor word) - uint16_t get_minor_os_version() const; - //Returns required operation system version (major word) - uint16_t get_major_os_version() const; - - //Sets required subsystem version - void set_subsystem_version(uint16_t major, uint16_t minor); - //Returns required subsystem version (minor word) - uint16_t get_minor_subsystem_version() const; - //Returns required subsystem version (major word) - uint16_t get_major_subsystem_version() const; - -public: //PE HEADER - //Returns DOS header - const pe_win::image_dos_header& get_dos_header() const; - pe_win::image_dos_header& get_dos_header(); - - //Returns PE header start (e_lfanew) - int32_t get_pe_header_start() const; - - //Returns file alignment - uint32_t get_file_alignment() const; - //Sets file alignment, checking the correctness of its value - void set_file_alignment(uint32_t alignment); - - //Returns size of image - uint32_t get_size_of_image() const; - - //Returns image entry point - uint32_t get_ep() const; - //Sets image entry point (just a value of PE header) - void set_ep(uint32_t new_ep); - - //Returns number of RVA and sizes (number of DATA_DIRECTORY entries) - uint32_t get_number_of_rvas_and_sizes() const; - //Sets number of RVA and sizes (number of DATA_DIRECTORY entries) - void set_number_of_rvas_and_sizes(uint32_t number); - - //Returns PE characteristics - uint16_t get_characteristics() const; - //Sets PE characteristics (a value inside header) - void set_characteristics(uint16_t ch); - //Clears PE characteristics flag - void clear_characteristics_flags(uint16_t flags); - //Sets PE characteristics flag - void set_characteristics_flags(uint16_t flags); - //Returns true if PE characteristics flag set - bool check_characteristics_flag(uint16_t flag) const; - - //Returns DLL Characteristics - uint16_t get_dll_characteristics() const; - //Sets DLL Characteristics - void set_dll_characteristics(uint16_t characteristics); - - //Returns size of headers - uint32_t get_size_of_headers() const; - //Returns size of optional header - uint16_t get_size_of_optional_header() const; - - //Returns PE signature - uint32_t get_pe_signature() const; - - //Returns magic value - uint32_t get_magic() const; - - //Returns image base for PE32 and PE64 respectively - uint32_t get_image_base_32() const; - void get_image_base(uint32_t& base) const; - //Sets image base for PE32 and PE64 respectively - uint64_t get_image_base_64() const; - void get_image_base(uint64_t& base) const; - - //Sets new image base - void set_image_base(uint32_t base); - void set_image_base_64(uint64_t base); - - //Sets heap size commit for PE32 and PE64 respectively - void set_heap_size_commit(uint32_t size); - void set_heap_size_commit(uint64_t size); - //Sets heap size reserve for PE32 and PE64 respectively - void set_heap_size_reserve(uint32_t size); - void set_heap_size_reserve(uint64_t size); - //Sets stack size commit for PE32 and PE64 respectively - void set_stack_size_commit(uint32_t size); - void set_stack_size_commit(uint64_t size); - //Sets stack size reserve for PE32 and PE64 respectively - void set_stack_size_reserve(uint32_t size); - void set_stack_size_reserve(uint64_t size); - - //Returns heap size commit for PE32 and PE64 respectively - uint32_t get_heap_size_commit_32() const; - void get_heap_size_commit(uint32_t& size) const; - uint64_t get_heap_size_commit_64() const; - void get_heap_size_commit(uint64_t& size) const; - //Returns heap size reserve for PE32 and PE64 respectively - uint32_t get_heap_size_reserve_32() const; - void get_heap_size_reserve(uint32_t& size) const; - uint64_t get_heap_size_reserve_64() const; - void get_heap_size_reserve(uint64_t& size) const; - //Returns stack size commit for PE32 and PE64 respectively - uint32_t get_stack_size_commit_32() const; - void get_stack_size_commit(uint32_t& size) const; - uint64_t get_stack_size_commit_64() const; - void get_stack_size_commit(uint64_t& size) const; - //Returns stack size reserve for PE32 and PE64 respectively - uint32_t get_stack_size_reserve_32() const; - void get_stack_size_reserve(uint32_t& size) const; - uint64_t get_stack_size_reserve_64() const; - void get_stack_size_reserve(uint64_t& size) const; - - //Updates virtual size of image corresponding to section virtual sizes - void update_image_size(); - - //Returns checksum of PE file from header - uint32_t get_checksum() const; - //Sets checksum of PE file - void set_checksum(uint32_t checksum); - - //Returns timestamp of PE file from header - uint32_t get_time_date_stamp() const; - //Sets timestamp of PE file - void set_time_date_stamp(uint32_t timestamp); - - //Returns Machine field value of PE file from header - uint16_t get_machine() const; - //Sets Machine field value of PE file - void set_machine(uint16_t machine); - - //Returns data from the beginning of image - //Size = SizeOfHeaders - const std::string& get_full_headers_data() const; - - typedef std::multimap<uint32_t, std::string> debug_data_list; - //Returns raw list of debug data - const debug_data_list& get_raw_debug_data_list() const; - - //Reads and checks DOS header - static void read_dos_header(std::istream& file, pe_win::image_dos_header& header); - - //Returns sizeof() nt headers - uint32_t get_sizeof_nt_header() const; - //Returns sizeof() optional headers - uint32_t get_sizeof_opt_headers() const; - //Returns raw nt headers data pointer - const char* get_nt_headers_ptr() const; - - //Sets size of headers (to NT headers) - void set_size_of_headers(uint32_t size); - //Sets size of optional headers (to NT headers) - void set_size_of_optional_header(uint16_t size); - - //Sets base of code - void set_base_of_code(uint32_t base); - //Returns base of code - uint32_t get_base_of_code() const; - -public: //ADDRESS CONVERTIONS - //Virtual Address (VA) to Relative Virtual Address (RVA) convertions - //for PE32 and PE64 respectively - //bound_check checks integer overflow - uint32_t va_to_rva(uint32_t va, bool bound_check = true) const; - uint32_t va_to_rva(uint64_t va, bool bound_check = true) const; - - //Relative Virtual Address (RVA) to Virtual Address (VA) convertions - //for PE32 and PE64 respectively - uint32_t rva_to_va_32(uint32_t rva) const; - void rva_to_va(uint32_t rva, uint32_t& va) const; - uint64_t rva_to_va_64(uint32_t rva) const; - void rva_to_va(uint32_t rva, uint64_t& va) const; - - //RVA to RAW file offset convertion (4gb max) - uint32_t rva_to_file_offset(uint32_t rva) const; - //RAW file offset to RVA convertion (4gb max) - uint32_t file_offset_to_rva(uint32_t offset) const; - - //RVA from section raw data offset - static uint32_t rva_from_section_offset(const section& s, uint32_t raw_offset_from_section_start); - -public: //IMAGE SECTIONS - //Returns number of sections from PE header - uint16_t get_number_of_sections() const; - - //Updates number of sections in PE header - uint16_t update_number_of_sections(); - - //Returns section alignment - uint32_t get_section_alignment() const; - - //Returns section list - section_list& get_image_sections(); - const section_list& get_image_sections() const; - - //Realigns all sections, if you made any changes to sections or alignments - void realign_all_sections(); - //Resligns section with specified index - void realign_section(uint32_t index); - - //Returns section from RVA inside it - section& section_from_rva(uint32_t rva); - const section& section_from_rva(uint32_t rva) const; - //Returns section from directory ID - section& section_from_directory(uint32_t directory_id); - const section& section_from_directory(uint32_t directory_id) const; - //Returns section from VA inside it for PE32 and PE64 respectively - section& section_from_va(uint32_t va); - const section& section_from_va(uint32_t va) const; - section& section_from_va(uint64_t va); - const section& section_from_va(uint64_t va) const; - //Returns section from file offset (4gb max) - section& section_from_file_offset(uint32_t offset); - const section& section_from_file_offset(uint32_t offset) const; - - //Returns section TOTAL RAW/VIRTUAL data length from RVA inside section - //If include_headers = true, data from the beginning of PE file to SizeOfHeaders will be searched, too - uint32_t section_data_length_from_rva(uint32_t rva, section_data_type datatype = section_data_raw, bool include_headers = false) const; - //Returns section TOTAL RAW/VIRTUAL data length from VA inside section for PE32 and PE64 respectively - //If include_headers = true, data from the beginning of PE file to SizeOfHeaders will be searched, too - uint32_t section_data_length_from_va(uint32_t va, section_data_type datatype = section_data_raw, bool include_headers = false) const; - uint32_t section_data_length_from_va(uint64_t va, section_data_type datatype = section_data_raw, bool include_headers = false) const; - - //Returns section remaining RAW/VIRTUAL data length from RVA to the end of section "s" (checks bounds) - uint32_t section_data_length_from_rva(const section& s, uint32_t rva_inside, section_data_type datatype = section_data_raw) const; - //Returns section remaining RAW/VIRTUAL data length from VA to the end of section "s" for PE32 and PE64 respectively (checks bounds) - uint32_t section_data_length_from_va(const section& s, uint64_t va_inside, section_data_type datatype = section_data_raw) const; - uint32_t section_data_length_from_va(const section& s, uint32_t va_inside, section_data_type datatype = section_data_raw) const; - - //Returns section remaining RAW/VIRTUAL data length from RVA "rva_inside" to the end of section containing RVA "rva" - //If include_headers = true, data from the beginning of PE file to SizeOfHeaders will be searched, too - uint32_t section_data_length_from_rva(uint32_t rva, uint32_t rva_inside, section_data_type datatype = section_data_raw, bool include_headers = false) const; - //Returns section remaining RAW/VIRTUAL data length from VA "va_inside" to the end of section containing VA "va" for PE32 and PE64 respectively - //If include_headers = true, data from the beginning of PE file to SizeOfHeaders will be searched, too - uint32_t section_data_length_from_va(uint32_t va, uint32_t va_inside, section_data_type datatype = section_data_raw, bool include_headers = false) const; - uint32_t section_data_length_from_va(uint64_t va, uint64_t va_inside, section_data_type datatype = section_data_raw, bool include_headers = false) const; - - //If include_headers = true, data from the beginning of PE file to SizeOfHeaders will be searched, too - //Returns corresponding section data pointer from RVA inside section - char* section_data_from_rva(uint32_t rva, bool include_headers = false); - const char* section_data_from_rva(uint32_t rva, section_data_type datatype = section_data_raw, bool include_headers = false) const; - //Returns corresponding section data pointer from VA inside section for PE32 and PE64 respectively - char* section_data_from_va(uint32_t va, bool include_headers = false); - const char* section_data_from_va(uint32_t va, section_data_type datatype = section_data_raw, bool include_headers = false) const; - char* section_data_from_va(uint64_t va, bool include_headers = false); - const char* section_data_from_va(uint64_t va, section_data_type datatype = section_data_raw, bool include_headers = false) const; - - //Returns corresponding section data pointer from RVA inside section "s" (checks bounds) - char* section_data_from_rva(section& s, uint32_t rva); - const char* section_data_from_rva(const section& s, uint32_t rva, section_data_type datatype = section_data_raw) const; - //Returns corresponding section data pointer from VA inside section "s" for PE32 and PE64 respectively (checks bounds) - char* section_data_from_va(section& s, uint32_t va); //Always returns raw data - const char* section_data_from_va(const section& s, uint32_t va, section_data_type datatype = section_data_raw) const; - char* section_data_from_va(section& s, uint64_t va); //Always returns raw data - const char* section_data_from_va(const section& s, uint64_t va, section_data_type datatype = section_data_raw) const; - - //Returns corresponding section data pointer from RVA inside section "s" (checks bounds, checks sizes, the most safe function) - template<typename T> - T section_data_from_rva(const section& s, uint32_t rva, section_data_type datatype = section_data_raw) const - { - if(rva >= s.get_virtual_address() && rva < s.get_virtual_address() + s.get_aligned_virtual_size(get_section_alignment()) && pe_utils::is_sum_safe(rva, sizeof(T))) - { - const std::string& data = datatype == section_data_raw ? s.get_raw_data() : s.get_virtual_data(get_section_alignment()); - //Don't check for underflow here, comparsion is unsigned - if(data.size() < rva - s.get_virtual_address() + sizeof(T)) - throw pe_exception("RVA and requested data size does not exist inside section", pe_exception::rva_not_exists); - - return *reinterpret_cast<const T*>(data.data() + rva - s.get_virtual_address()); - } - - throw pe_exception("RVA not found inside section", pe_exception::rva_not_exists); - } - - //Returns corresponding section data pointer from RVA inside section (checks rva, checks sizes, the most safe function) - //If include_headers = true, data from the beginning of PE file to SizeOfHeaders will be searched, too - template<typename T> - T section_data_from_rva(uint32_t rva, section_data_type datatype = section_data_raw, bool include_headers = false) const - { - //if RVA is inside of headers and we're searching them too... - if(include_headers && pe_utils::is_sum_safe(rva, sizeof(T)) && (rva + sizeof(T) < full_headers_data_.length())) - return *reinterpret_cast<const T*>(&full_headers_data_[rva]); - - const section& s = section_from_rva(rva); - const std::string& data = datatype == section_data_raw ? s.get_raw_data() : s.get_virtual_data(get_section_alignment()); - //Don't check for underflow here, comparsion is unsigned - if(data.size() < rva - s.get_virtual_address() + sizeof(T)) - throw pe_exception("RVA and requested data size does not exist inside section", pe_exception::rva_not_exists); - - return *reinterpret_cast<const T*>(data.data() + rva - s.get_virtual_address()); - } - - //Returns corresponding section data pointer from VA inside section "s" (checks bounds, checks sizes, the most safe function) - template<typename T> - T section_data_from_va(const section& s, uint32_t va, section_data_type datatype = section_data_raw) const - { - return section_data_from_rva<T>(s, va_to_rva(va), datatype); - } - - template<typename T> - T section_data_from_va(const section& s, uint64_t va, section_data_type datatype = section_data_raw) const - { - return section_data_from_rva<T>(s, va_to_rva(va), datatype); - } - - //Returns corresponding section data pointer from VA inside section (checks rva, checks sizes, the most safe function) - //If include_headers = true, data from the beginning of PE file to SizeOfHeaders will be searched, too - template<typename T> - T section_data_from_va(uint32_t va, section_data_type datatype = section_data_raw, bool include_headers = false) const - { - return section_data_from_rva<T>(va_to_rva(va), datatype, include_headers); - } - - template<typename T> - T section_data_from_va(uint64_t va, section_data_type datatype = section_data_raw, bool include_headers = false) const - { - return section_data_from_rva<T>(va_to_rva(va), datatype, include_headers); - } - - //Returns section and offset (raw data only) from its start from RVA - const std::pair<uint32_t, const section*> section_and_offset_from_rva(uint32_t rva) const; - - //Sets virtual size of section "s" - //Section must be free (not bound to any image) - //or the last section of this image - //Function calls update_image_size automatically in second case - void set_section_virtual_size(section& s, uint32_t vsize); - - //Represents section expand type for expand_section function - enum section_expand_type - { - expand_section_raw, //Section raw data size will be expanded - expand_section_virtual //Section virtual data size will be expanded - }; - - //Expands section raw or virtual size to hold data from specified RVA with specified size - //Section must be free (not bound to any image) - //or the last section of this image - //Returns true if section was expanded - bool expand_section(section& s, uint32_t needed_rva, uint32_t needed_size, section_expand_type expand); - - //Adds section to image - //Returns last section - section& add_section(section s); - //Prepares section to later add it to image (checks and recalculates virtual and raw section size) - //Section must be prepared by this function before calling add_section - void prepare_section(section& s); - - //Returns true if sectios "s" is already attached to this PE file - bool section_attached(const section& s) const; - - -public: //IMAGE - //Returns PE type (PE or PE+) from pe_type enumeration (minimal correctness checks) - static pe_type get_pe_type(std::istream& file); - //Returns PE type of this image - pe_type get_pe_type() const; - - //Returns true if image has overlay data at the end of file - bool has_overlay() const; - - //Realigns file (changes file alignment) - void realign_file(uint32_t new_file_alignment); - - //Helper function to recalculate RAW and virtual section sizes and strip it, if necessary - //auto_strip = strip section, if necessary - void recalculate_section_sizes(section& s, bool auto_strip); - - // ========== END OF PUBLIC MEMBERS AND STRUCTURES ========== // -private: - //Image DOS header - pe_win::image_dos_header dos_header_; - //Rich (stub) overlay data (for MSVS) - std::string rich_overlay_; - //List of image sections - section_list sections_; - //True if image has overlay - bool has_overlay_; - //Raw SizeOfHeaders-sized data from the beginning of image - std::string full_headers_data_; - //Raw debug data for all directories - //PointerToRawData; Data - debug_data_list debug_data_; - //PE or PE+ related properties - pe_properties* props_; - - //Reads and checks DOS header - void read_dos_header(std::istream& file); - - //Reads and checks PE headers and section headers, data - void read_pe(std::istream& file, bool read_debug_raw_data); - - //Sets number of sections - void set_number_of_sections(uint16_t number); - //Sets size of image - void set_size_of_image(uint32_t size); - //Sets file alignment (no checks) - void set_file_alignment_unchecked(uint32_t alignment); - //Returns needed magic of image - uint32_t get_needed_magic() const; - //Returns nt headers data pointer - char* get_nt_headers_ptr(); - -private: - static const uint16_t maximum_number_of_sections = 0x60; - static const uint32_t minimum_file_alignment = 512; - -private: - //RAW file offset to section convertion helpers (4gb max) - section_list::const_iterator file_offset_to_section(uint32_t offset) const; - section_list::iterator file_offset_to_section(uint32_t offset); -}; -} diff --git a/tools/pe_bliss/pe_bliss.h b/tools/pe_bliss/pe_bliss.h deleted file mode 100644 index 1a8b430284..0000000000 --- a/tools/pe_bliss/pe_bliss.h +++ /dev/null @@ -1,39 +0,0 @@ -/*************************************************************************/ -/* Copyright (c) 2015 dx, http://kaimi.ru */ -/* */ -/* Permission is hereby granted, free of charge, to any person */ -/* obtaining a copy of this software and associated documentation */ -/* files (the "Software"), to deal in the Software without */ -/* restriction, including without limitation the rights to use, */ -/* copy, modify, merge, publish, distribute, sublicense, and/or */ -/* sell copies of the Software, and to permit persons to whom the */ -/* Software is furnished to do so, subject to the following conditions: */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#pragma once -#include "pe_base.h" -#include "pe_rebuilder.h" -#include "pe_factory.h" -#include "pe_bound_import.h" -#include "pe_debug.h" -#include "pe_dotnet.h" -#include "pe_exception_directory.h" -#include "pe_exports.h" -#include "pe_imports.h" -#include "pe_load_config.h" -#include "pe_relocations.h" -#include "pe_resources.h" -#include "pe_rich_data.h" -#include "pe_tls.h" -#include "pe_properties_generic.h" -#include "pe_checksum.h" -#include "entropy.h" diff --git a/tools/pe_bliss/pe_bliss_godot.cpp b/tools/pe_bliss/pe_bliss_godot.cpp deleted file mode 100644 index 8297aa1045..0000000000 --- a/tools/pe_bliss/pe_bliss_godot.cpp +++ /dev/null @@ -1,118 +0,0 @@ -#include "pe_bliss/pe_bliss.h" -#include "pe_bliss/pe_bliss_resources.h" -#include "core/ustring.h" -#include "core/dvector.h" -#include "os/file_access.h" - -using namespace pe_bliss; - -String pe_bliss_add_resrc(const char* p_path, int version_major, int version_minor, - String& company_name, String& file_description, - String& legal_copyright, String& version_text, - String& product_name, String& godot_version, - DVector<uint8_t>& icon_content) { - try - { - pe_base image(pe_factory::create_pe(p_path)); - - const section_list& pe_sections = image.get_image_sections(); - uint32_t end_of_pe = 0; - FileAccess *dst; - DVector<uint8_t> overlay_data; - if(image.has_overlay()) - { - end_of_pe = pe_sections.back().get_pointer_to_raw_data() + pe_sections.back().get_size_of_raw_data(); - dst=FileAccess::open(p_path,FileAccess::READ); - if (dst) { - overlay_data.resize(dst->get_len()-end_of_pe); - dst->seek(end_of_pe); - DVector<uint8_t>::Write overlay_data_write = overlay_data.write(); - dst->get_buffer(overlay_data_write.ptr(),overlay_data.size()); - dst->close(); - memdelete(dst); - } - } - resource_directory root; - if(image.has_resources()) - { - root = resource_directory(get_resources(image)); - } - pe_resource_manager res(root); - if(image.has_resources()) - { - if(icon_content.size()) { - if(res.resource_exists(pe_resource_viewer::resource_icon)) - { - res.remove_resource_type(pe_resource_viewer::resource_icon); - } - if(res.resource_exists(pe_resource_viewer::resource_icon_group)) - { - res.remove_resource_type(pe_resource_viewer::resource_icon_group); - } - } - if(res.resource_exists(pe_resource_viewer::resource_version)) - { - res.remove_resource_type(pe_resource_viewer::resource_version); - } - } - file_version_info file_info; - file_info.set_file_os(file_version_info::file_os_nt_win32); - file_info.set_file_type(file_version_info::file_type_application); - unsigned int ver = version_major << 16; - ver = ver + version_minor; - file_info.set_file_version_ms(ver); - file_info.set_file_version_ls(0x00000000); - file_info.set_product_version_ms(ver); - file_info.set_product_version_ls(0x00000000); - lang_string_values_map strings; - translation_values_map translations; - version_info_editor version(strings, translations); - version.add_translation(version_info_editor::default_language_translation); - version.set_company_name(company_name.c_str()); - version.set_file_description(file_description.c_str()); - if (!product_name.empty()) { - version.set_internal_name((product_name+String(".exe")).c_str()); - version.set_original_filename((product_name+String(".exe")).c_str()); - version.set_product_name(product_name.c_str()); - } - version.set_legal_copyright(legal_copyright.c_str()); - version.set_product_version(version_text.c_str()); - if(!godot_version.empty()) version.set_property(L"Godot Engine Version", godot_version.c_str() ); - resource_version_info_writer(res).set_version_info(file_info, strings, translations, 1033, 1200); - if(icon_content.size()) { - std::string icon; - icon.resize(icon_content.size()); - for(int i=0; i<icon_content.size(); i++) - { - icon[i] = icon_content[i]; - } - resource_cursor_icon_writer(res).add_icon(icon, L"MAIN_ICON", 1033); - } - if(image.has_resources()) - { - rebuild_resources(image, root, image.section_from_directory(pe_win::image_directory_entry_resource)); - } else { - section new_resources; - new_resources.get_raw_data().resize(1); - new_resources.set_name(".rsrc"); - new_resources.readable(true); - section& attached_section = image.add_section(new_resources); - rebuild_resources(image, root, attached_section); - } - rebuild_pe(image, p_path); - if(image.has_overlay() && end_of_pe) { - dst=FileAccess::open(p_path,FileAccess::READ_WRITE); - if (dst) { - dst->seek_end(); - DVector<uint8_t>::Read overlay_data_read = overlay_data.read(); - dst->store_buffer(overlay_data_read.ptr(),overlay_data.size()); - dst->close(); - memdelete(dst); - } - } - return String(); - } catch(const pe_exception& e) { - String ret("Error In Add rsrc Section : "); - return ret + String(e.what()); - } -} diff --git a/tools/pe_bliss/pe_bliss_godot.h b/tools/pe_bliss/pe_bliss_godot.h deleted file mode 100644 index 0365ca9eaf..0000000000 --- a/tools/pe_bliss/pe_bliss_godot.h +++ /dev/null @@ -1,7 +0,0 @@ - - -String pe_bliss_add_resrc(const char* p_path, int version_major, int version_minor, - String& company_name, String& file_description, - String& legal_copyright, String& version_text, - String& product_name, String& godot_version, - DVector<uint8_t>& icon_content); diff --git a/tools/pe_bliss/pe_bliss_resources.h b/tools/pe_bliss/pe_bliss_resources.h deleted file mode 100644 index 60369f8011..0000000000 --- a/tools/pe_bliss/pe_bliss_resources.h +++ /dev/null @@ -1,36 +0,0 @@ -/*************************************************************************/ -/* Copyright (c) 2015 dx, http://kaimi.ru */ -/* */ -/* Permission is hereby granted, free of charge, to any person */ -/* obtaining a copy of this software and associated documentation */ -/* files (the "Software"), to deal in the Software without */ -/* restriction, including without limitation the rights to use, */ -/* copy, modify, merge, publish, distribute, sublicense, and/or */ -/* sell copies of the Software, and to permit persons to whom the */ -/* Software is furnished to do so, subject to the following conditions: */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#pragma once -#include "file_version_info.h" -#include "message_table.h" -#include "pe_resource_manager.h" -#include "pe_resource_viewer.h" -#include "version_info_editor.h" -#include "version_info_viewer.h" -#include "resource_bitmap_reader.h" -#include "resource_bitmap_writer.h" -#include "resource_cursor_icon_reader.h" -#include "resource_cursor_icon_writer.h" -#include "resource_version_info_reader.h" -#include "resource_version_info_writer.h" -#include "resource_string_table_reader.h" -#include "resource_message_list_reader.h" diff --git a/tools/pe_bliss/pe_bound_import.cpp b/tools/pe_bliss/pe_bound_import.cpp deleted file mode 100644 index 4b54b36105..0000000000 --- a/tools/pe_bliss/pe_bound_import.cpp +++ /dev/null @@ -1,311 +0,0 @@ -/*************************************************************************/ -/* Copyright (c) 2015 dx, http://kaimi.ru */ -/* */ -/* Permission is hereby granted, free of charge, to any person */ -/* obtaining a copy of this software and associated documentation */ -/* files (the "Software"), to deal in the Software without */ -/* restriction, including without limitation the rights to use, */ -/* copy, modify, merge, publish, distribute, sublicense, and/or */ -/* sell copies of the Software, and to permit persons to whom the */ -/* Software is furnished to do so, subject to the following conditions: */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#include <string.h> -#include "pe_bound_import.h" -#include "utils.h" - -namespace pe_bliss -{ -using namespace pe_win; - -//BOUND IMPORT -//Default constructor -bound_import_ref::bound_import_ref() - :timestamp_(0) -{} - -//Constructor from data -bound_import_ref::bound_import_ref(const std::string& module_name, uint32_t timestamp) - :module_name_(module_name), timestamp_(timestamp) -{} - -//Returns imported module name -const std::string& bound_import_ref::get_module_name() const -{ - return module_name_; -} - -//Returns bound import date and time stamp -uint32_t bound_import_ref::get_timestamp() const -{ - return timestamp_; -} - -//Sets module name -void bound_import_ref::set_module_name(const std::string& module_name) -{ - module_name_ = module_name; -} - -//Sets timestamp -void bound_import_ref::set_timestamp(uint32_t timestamp) -{ - timestamp_ = timestamp; -} - -//Default constructor -bound_import::bound_import() - :timestamp_(0) -{} - -//Constructor from data -bound_import::bound_import(const std::string& module_name, uint32_t timestamp) - :module_name_(module_name), timestamp_(timestamp) -{} - -//Returns imported module name -const std::string& bound_import::get_module_name() const -{ - return module_name_; -} - -//Returns bound import date and time stamp -uint32_t bound_import::get_timestamp() const -{ - return timestamp_; -} - -//Returns bound references cound -size_t bound_import::get_module_ref_count() const -{ - return refs_.size(); -} - -//Returns module references -const bound_import::ref_list& bound_import::get_module_ref_list() const -{ - return refs_; -} - -//Adds module reference -void bound_import::add_module_ref(const bound_import_ref& ref) -{ - refs_.push_back(ref); -} - -//Clears module references list -void bound_import::clear_module_refs() -{ - refs_.clear(); -} - -//Returns module references -bound_import::ref_list& bound_import::get_module_ref_list() -{ - return refs_; -} - -//Sets module name -void bound_import::set_module_name(const std::string& module_name) -{ - module_name_ = module_name; -} - -//Sets timestamp -void bound_import::set_timestamp(uint32_t timestamp) -{ - timestamp_ = timestamp; -} - -const bound_import_module_list get_bound_import_module_list(const pe_base& pe) -{ - //Returned bound import modules list - bound_import_module_list ret; - - //If image has no bound imports - if(!pe.has_bound_import()) - return ret; - - uint32_t bound_import_data_len = - pe.section_data_length_from_rva(pe.get_directory_rva(image_directory_entry_bound_import), pe.get_directory_rva(image_directory_entry_bound_import), section_data_raw, true); - - if(bound_import_data_len < pe.get_directory_size(image_directory_entry_bound_import)) - throw pe_exception("Incorrect bound import directory", pe_exception::incorrect_bound_import_directory); - - const char* bound_import_data = pe.section_data_from_rva(pe.get_directory_rva(image_directory_entry_bound_import), section_data_raw, true); - - //Check read in "read_pe" function raw bound import data size - if(bound_import_data_len < sizeof(image_bound_import_descriptor)) - throw pe_exception("Incorrect bound import directory", pe_exception::incorrect_bound_import_directory); - - //current bound_import_data_ in-string position - unsigned long current_pos = 0; - //first bound import descriptor - //so, we're working with raw data here, no section helpers available - const image_bound_import_descriptor* descriptor = reinterpret_cast<const image_bound_import_descriptor*>(&bound_import_data[current_pos]); - - //Enumerate until zero - while(descriptor->OffsetModuleName) - { - //Check module name offset - if(descriptor->OffsetModuleName >= bound_import_data_len) - throw pe_exception("Incorrect bound import directory", pe_exception::incorrect_bound_import_directory); - - //Check module name for null-termination - if(!pe_utils::is_null_terminated(&bound_import_data[descriptor->OffsetModuleName], bound_import_data_len - descriptor->OffsetModuleName)) - throw pe_exception("Incorrect bound import directory", pe_exception::incorrect_bound_import_directory); - - //Create bound import descriptor structure - bound_import elem(&bound_import_data[descriptor->OffsetModuleName], descriptor->TimeDateStamp); - - //Check DWORDs - if(descriptor->NumberOfModuleForwarderRefs >= pe_utils::max_dword / sizeof(image_bound_forwarder_ref) - || !pe_utils::is_sum_safe(current_pos, 2 /* this descriptor and the next one */ * sizeof(image_bound_import_descriptor) + descriptor->NumberOfModuleForwarderRefs * sizeof(image_bound_forwarder_ref))) - throw pe_exception("Incorrect bound import directory", pe_exception::incorrect_bound_import_directory); - - //Move after current descriptor - current_pos += sizeof(image_bound_import_descriptor); - - //Enumerate referenced bound import descriptors - for(unsigned long i = 0; i != descriptor->NumberOfModuleForwarderRefs; ++i) - { - //They're just after parent descriptor - //Check size of structure - if(current_pos + sizeof(image_bound_forwarder_ref) > bound_import_data_len) - throw pe_exception("Incorrect bound import directory", pe_exception::incorrect_bound_import_directory); - - //Get IMAGE_BOUND_FORWARDER_REF pointer - const image_bound_forwarder_ref* ref_descriptor = reinterpret_cast<const image_bound_forwarder_ref*>(&bound_import_data[current_pos]); - - //Check referenced module name - if(ref_descriptor->OffsetModuleName >= bound_import_data_len) - throw pe_exception("Incorrect bound import directory", pe_exception::incorrect_bound_import_directory); - - //And its null-termination - if(!pe_utils::is_null_terminated(&bound_import_data[ref_descriptor->OffsetModuleName], bound_import_data_len - ref_descriptor->OffsetModuleName)) - throw pe_exception("Incorrect bound import directory", pe_exception::incorrect_bound_import_directory); - - //Add referenced module to current bound import structure - elem.add_module_ref(bound_import_ref(&bound_import_data[ref_descriptor->OffsetModuleName], ref_descriptor->TimeDateStamp)); - - //Move after referenced bound import descriptor - current_pos += sizeof(image_bound_forwarder_ref); - } - - //Check structure size - if(current_pos + sizeof(image_bound_import_descriptor) > bound_import_data_len) - throw pe_exception("Incorrect bound import directory", pe_exception::incorrect_bound_import_directory); - - //Move to next bound import descriptor - descriptor = reinterpret_cast<const image_bound_import_descriptor*>(&bound_import_data[current_pos]); - - //Save created descriptor structure and references - ret.push_back(elem); - } - - //Return result - return ret; -} - -//imports - bound imported modules list -//imports_section - section where export directory will be placed (must be attached to PE image) -//offset_from_section_start - offset from imports_section raw data start -//save_to_pe_headers - if true, new bound import directory information will be saved to PE image headers -//auto_strip_last_section - if true and bound imports are placed in the last section, it will be automatically stripped -const image_directory rebuild_bound_imports(pe_base& pe, const bound_import_module_list& imports, section& imports_section, uint32_t offset_from_section_start, bool save_to_pe_header, bool auto_strip_last_section) -{ - //Check that exports_section is attached to this PE image - if(!pe.section_attached(imports_section)) - throw pe_exception("Bound import section must be attached to PE file", pe_exception::section_is_not_attached); - - uint32_t directory_pos = pe_utils::align_up(offset_from_section_start, sizeof(uint32_t)); - uint32_t needed_size = sizeof(image_bound_import_descriptor) /* Ending null descriptor */; - uint32_t needed_size_for_strings = 0; - - //Calculate needed size for bound import data - for(bound_import_module_list::const_iterator it = imports.begin(); it != imports.end(); ++it) - { - const bound_import& import = *it; - needed_size += sizeof(image_bound_import_descriptor); - needed_size_for_strings += static_cast<uint32_t>((*it).get_module_name().length()) + 1 /* nullbyte */; - - const bound_import::ref_list& refs = import.get_module_ref_list(); - for(bound_import::ref_list::const_iterator ref_it = refs.begin(); ref_it != refs.end(); ++ref_it) - { - needed_size_for_strings += static_cast<uint32_t>((*ref_it).get_module_name().length()) + 1 /* nullbyte */; - needed_size += sizeof(image_bound_forwarder_ref); - } - } - - needed_size += needed_size_for_strings; - - //Check if imports_section is last one. If it's not, check if there's enough place for bound import data - if(&imports_section != &*(pe.get_image_sections().end() - 1) && - (imports_section.empty() || pe_utils::align_up(imports_section.get_size_of_raw_data(), pe.get_file_alignment()) < needed_size + directory_pos)) - throw pe_exception("Insufficient space for bound import directory", pe_exception::insufficient_space); - - std::string& raw_data = imports_section.get_raw_data(); - - //This will be done only if imports_section is the last section of image or for section with unaligned raw length of data - if(raw_data.length() < needed_size + directory_pos) - raw_data.resize(needed_size + directory_pos); //Expand section raw data - - uint32_t current_pos_for_structures = directory_pos; - uint32_t current_pos_for_strings = current_pos_for_structures + needed_size - needed_size_for_strings; - - for(bound_import_module_list::const_iterator it = imports.begin(); it != imports.end(); ++it) - { - const bound_import& import = *it; - image_bound_import_descriptor descriptor; - descriptor.NumberOfModuleForwarderRefs = static_cast<uint16_t>(import.get_module_ref_list().size()); - descriptor.OffsetModuleName = static_cast<uint16_t>(current_pos_for_strings - directory_pos); - descriptor.TimeDateStamp = import.get_timestamp(); - - memcpy(&raw_data[current_pos_for_structures], &descriptor, sizeof(descriptor)); - current_pos_for_structures += sizeof(descriptor); - - size_t length = import.get_module_name().length() + 1 /* nullbyte */; - memcpy(&raw_data[current_pos_for_strings], import.get_module_name().c_str(), length); - current_pos_for_strings += static_cast<uint32_t>(length); - - const bound_import::ref_list& refs = import.get_module_ref_list(); - for(bound_import::ref_list::const_iterator ref_it = refs.begin(); ref_it != refs.end(); ++ref_it) - { - const bound_import_ref& ref = *ref_it; - image_bound_forwarder_ref ref_descriptor = {0}; - ref_descriptor.OffsetModuleName = static_cast<uint16_t>(current_pos_for_strings - directory_pos); - ref_descriptor.TimeDateStamp = ref.get_timestamp(); - - memcpy(&raw_data[current_pos_for_structures], &ref_descriptor, sizeof(ref_descriptor)); - current_pos_for_structures += sizeof(ref_descriptor); - - length = ref.get_module_name().length() + 1 /* nullbyte */; - memcpy(&raw_data[current_pos_for_strings], ref.get_module_name().c_str(), length); - current_pos_for_strings += static_cast<uint32_t>(length); - } - } - - //Adjust section raw and virtual sizes - pe.recalculate_section_sizes(imports_section, auto_strip_last_section); - - image_directory ret(pe.rva_from_section_offset(imports_section, directory_pos), needed_size); - - //If auto-rewrite of PE headers is required - if(save_to_pe_header) - { - pe.set_directory_rva(image_directory_entry_bound_import, ret.get_rva()); - pe.set_directory_size(image_directory_entry_bound_import, ret.get_size()); - } - - return ret; -} -} diff --git a/tools/pe_bliss/pe_bound_import.h b/tools/pe_bliss/pe_bound_import.h deleted file mode 100644 index 667e28792e..0000000000 --- a/tools/pe_bliss/pe_bound_import.h +++ /dev/null @@ -1,108 +0,0 @@ -/*************************************************************************/ -/* Copyright (c) 2015 dx, http://kaimi.ru */ -/* */ -/* Permission is hereby granted, free of charge, to any person */ -/* obtaining a copy of this software and associated documentation */ -/* files (the "Software"), to deal in the Software without */ -/* restriction, including without limitation the rights to use, */ -/* copy, modify, merge, publish, distribute, sublicense, and/or */ -/* sell copies of the Software, and to permit persons to whom the */ -/* Software is furnished to do so, subject to the following conditions: */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#pragma once -#include <vector> -#include <string> -#include "pe_structures.h" -#include "pe_base.h" -#include "pe_directory.h" - -namespace pe_bliss -{ -//Class representing bound import reference -class bound_import_ref -{ -public: - //Default constructor - bound_import_ref(); - //Constructor from data - bound_import_ref(const std::string& module_name, uint32_t timestamp); - - //Returns imported module name - const std::string& get_module_name() const; - //Returns bound import date and time stamp - uint32_t get_timestamp() const; - -public: //Setters - //Sets module name - void set_module_name(const std::string& module_name); - //Sets timestamp - void set_timestamp(uint32_t timestamp); - -private: - std::string module_name_; //Imported module name - uint32_t timestamp_; //Bound import timestamp -}; - -//Class representing image bound import information -class bound_import -{ -public: - typedef std::vector<bound_import_ref> ref_list; - -public: - //Default constructor - bound_import(); - //Constructor from data - bound_import(const std::string& module_name, uint32_t timestamp); - - //Returns imported module name - const std::string& get_module_name() const; - //Returns bound import date and time stamp - uint32_t get_timestamp() const; - - //Returns bound references cound - size_t get_module_ref_count() const; - //Returns module references - const ref_list& get_module_ref_list() const; - -public: //Setters - //Sets module name - void set_module_name(const std::string& module_name); - //Sets timestamp - void set_timestamp(uint32_t timestamp); - - //Adds module reference - void add_module_ref(const bound_import_ref& ref); - //Clears module references list - void clear_module_refs(); - //Returns module references - ref_list& get_module_ref_list(); - -private: - std::string module_name_; //Imported module name - uint32_t timestamp_; //Bound import timestamp - ref_list refs_; //Module references list -}; - -typedef std::vector<bound_import> bound_import_module_list; - -//Returns bound import information -const bound_import_module_list get_bound_import_module_list(const pe_base& pe);//Export directory rebuilder - -//imports - bound imported modules list -//imports_section - section where export directory will be placed (must be attached to PE image) -//offset_from_section_start - offset from imports_section raw data start -//save_to_pe_headers - if true, new bound import directory information will be saved to PE image headers -//auto_strip_last_section - if true and bound imports are placed in the last section, it will be automatically stripped -const image_directory rebuild_bound_imports(pe_base& pe, const bound_import_module_list& imports, section& imports_section, uint32_t offset_from_section_start = 0, bool save_to_pe_header = true, bool auto_strip_last_section = true); -} diff --git a/tools/pe_bliss/pe_checksum.cpp b/tools/pe_bliss/pe_checksum.cpp deleted file mode 100644 index 5971a33c90..0000000000 --- a/tools/pe_bliss/pe_checksum.cpp +++ /dev/null @@ -1,103 +0,0 @@ -/*************************************************************************/ -/* Copyright (c) 2015 dx, http://kaimi.ru */ -/* */ -/* Permission is hereby granted, free of charge, to any person */ -/* obtaining a copy of this software and associated documentation */ -/* files (the "Software"), to deal in the Software without */ -/* restriction, including without limitation the rights to use, */ -/* copy, modify, merge, publish, distribute, sublicense, and/or */ -/* sell copies of the Software, and to permit persons to whom the */ -/* Software is furnished to do so, subject to the following conditions: */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#include "pe_checksum.h" -#include "pe_structures.h" -#include "pe_base.h" - -namespace pe_bliss -{ -using namespace pe_win; - -//Calculate checksum of image -uint32_t calculate_checksum(std::istream& file) -{ - //Save istream state - std::ios_base::iostate state = file.exceptions(); - std::streamoff old_offset = file.tellg(); - - //Checksum value - unsigned long long checksum = 0; - - try - { - image_dos_header header; - - file.exceptions(std::ios::goodbit); - - //Read DOS header - pe_base::read_dos_header(file, header); - - //Calculate PE checksum - file.seekg(0); - unsigned long long top = 0xFFFFFFFF; - top++; - - //"CheckSum" field position in optional PE headers - it's always 64 for PE and PE+ - static const unsigned long checksum_pos_in_optional_headers = 64; - //Calculate real PE headers "CheckSum" field position - //Sum is safe here - unsigned long pe_checksum_pos = header.e_lfanew + sizeof(image_file_header) + sizeof(uint32_t) + checksum_pos_in_optional_headers; - - //Calculate checksum for each byte of file - std::streamoff filesize = pe_utils::get_file_size(file); - for(long long i = 0; i < filesize; i += 4) - { - unsigned long dw = 0; - - //Read DWORD from file - file.read(reinterpret_cast<char*>(&dw), sizeof(unsigned long)); - //Skip "CheckSum" DWORD - if(i == pe_checksum_pos) - continue; - - //Calculate checksum - checksum = (checksum & 0xffffffff) + dw + (checksum >> 32); - if(checksum > top) - checksum = (checksum & 0xffffffff) + (checksum >> 32); - } - - //Finish checksum - checksum = (checksum & 0xffff) + (checksum >> 16); - checksum = (checksum) + (checksum >> 16); - checksum = checksum & 0xffff; - - checksum += static_cast<unsigned long>(filesize); - } - catch(const std::exception&) - { - //If something went wrong, restore istream state - file.exceptions(state); - file.seekg(old_offset); - file.clear(); - //Rethrow - throw; - } - - //Restore istream state - file.exceptions(state); - file.seekg(old_offset); - file.clear(); - - //Return checksum - return static_cast<uint32_t>(checksum); -} -} diff --git a/tools/pe_bliss/pe_checksum.h b/tools/pe_bliss/pe_checksum.h deleted file mode 100644 index a568d5d369..0000000000 --- a/tools/pe_bliss/pe_checksum.h +++ /dev/null @@ -1,30 +0,0 @@ -/*************************************************************************/ -/* Copyright (c) 2015 dx, http://kaimi.ru */ -/* */ -/* Permission is hereby granted, free of charge, to any person */ -/* obtaining a copy of this software and associated documentation */ -/* files (the "Software"), to deal in the Software without */ -/* restriction, including without limitation the rights to use, */ -/* copy, modify, merge, publish, distribute, sublicense, and/or */ -/* sell copies of the Software, and to permit persons to whom the */ -/* Software is furnished to do so, subject to the following conditions: */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#pragma once -#include <istream> -#include "stdint_defs.h" - -namespace pe_bliss -{ -//Calculate checksum of image (performs no checks on PE structures) -uint32_t calculate_checksum(std::istream& file); -} diff --git a/tools/pe_bliss/pe_debug.cpp b/tools/pe_bliss/pe_debug.cpp deleted file mode 100644 index a0ed3f5af1..0000000000 --- a/tools/pe_bliss/pe_debug.cpp +++ /dev/null @@ -1,865 +0,0 @@ -/*************************************************************************/ -/* Copyright (c) 2015 dx, http://kaimi.ru */ -/* */ -/* Permission is hereby granted, free of charge, to any person */ -/* obtaining a copy of this software and associated documentation */ -/* files (the "Software"), to deal in the Software without */ -/* restriction, including without limitation the rights to use, */ -/* copy, modify, merge, publish, distribute, sublicense, and/or */ -/* sell copies of the Software, and to permit persons to whom the */ -/* Software is furnished to do so, subject to the following conditions: */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#include <string.h> -#include "pe_debug.h" -#include "utils.h" - -namespace pe_bliss -{ -using namespace pe_win; -//DEBUG -//Default constructor -debug_info::debug_info() - :characteristics_(0), - time_stamp_(0), - major_version_(0), minor_version_(0), - type_(0), - size_of_data_(0), - address_of_raw_data_(0), - pointer_to_raw_data_(0), - advanced_info_type_(advanced_info_none) -{} - -//Constructor from data -debug_info::debug_info(const image_debug_directory& debug) - :characteristics_(debug.Characteristics), - time_stamp_(debug.TimeDateStamp), - major_version_(debug.MajorVersion), minor_version_(debug.MinorVersion), - type_(debug.Type), - size_of_data_(debug.SizeOfData), - address_of_raw_data_(debug.AddressOfRawData), - pointer_to_raw_data_(debug.PointerToRawData), - advanced_info_type_(advanced_info_none) -{} - -//Returns debug characteristics -uint32_t debug_info::get_characteristics() const -{ - return characteristics_; -} - -//Returns debug datetimestamp -uint32_t debug_info::get_time_stamp() const -{ - return time_stamp_; -} - -//Returns major version -uint32_t debug_info::get_major_version() const -{ - return major_version_; -} - -//Returns minor version -uint32_t debug_info::get_minor_version() const -{ - return minor_version_; -} - -//Returns type of debug info (unchecked) -uint32_t debug_info::get_type_raw() const -{ - return type_; -} - -//Returns type of debug info from debug_info_type enumeration -debug_info::debug_info_type debug_info::get_type() const -{ - //Determine debug type - switch(type_) - { - case image_debug_type_coff: - return debug_type_coff; - - case image_debug_type_codeview: - return debug_type_codeview; - - case image_debug_type_fpo: - return debug_type_fpo; - - case image_debug_type_misc: - return debug_type_misc; - - case image_debug_type_exception: - return debug_type_exception; - - case image_debug_type_fixup: - return debug_type_fixup; - - case image_debug_type_omap_to_src: - return debug_type_omap_to_src; - - case image_debug_type_omap_from_src: - return debug_type_omap_from_src; - - case image_debug_type_borland: - return debug_type_borland; - - case image_debug_type_clsid: - return debug_type_clsid; - - case image_debug_type_reserved10: - return debug_type_reserved10; - } - - return debug_type_unknown; -} - -//Returns size of debug data (internal, .pdb or other file doesn't count) -uint32_t debug_info::get_size_of_data() const -{ - return size_of_data_; -} - -//Returns RVA of debug info when mapped to memory or zero, if info is not mapped -uint32_t debug_info::get_rva_of_raw_data() const -{ - return address_of_raw_data_; -} - -//Returns raw file pointer to raw data -uint32_t debug_info::get_pointer_to_raw_data() const -{ - return pointer_to_raw_data_; -} - -//Copy constructor -debug_info::debug_info(const debug_info& info) - :characteristics_(info.characteristics_), - time_stamp_(info.time_stamp_), - major_version_(info.major_version_), minor_version_(info.minor_version_), - type_(info.type_), - size_of_data_(info.size_of_data_), - address_of_raw_data_(info.address_of_raw_data_), - pointer_to_raw_data_(info.pointer_to_raw_data_), - advanced_info_type_(info.advanced_info_type_) -{ - copy_advanced_info(info); -} - -//Copy assignment operator -debug_info& debug_info::operator=(const debug_info& info) -{ - copy_advanced_info(info); - - characteristics_ = info.characteristics_; - time_stamp_ = info.time_stamp_; - major_version_ = info.major_version_; - minor_version_ = info.minor_version_; - type_ = info.type_; - size_of_data_ = info.size_of_data_; - address_of_raw_data_ = info.address_of_raw_data_; - pointer_to_raw_data_ = info.pointer_to_raw_data_; - advanced_info_type_ = info.advanced_info_type_; - - return *this; -} - -//Default constructor -debug_info::advanced_info::advanced_info() - :adv_pdb_7_0_info(0) //Zero pointer to advanced data -{} - -//Returns true if advanced debug info is present -bool debug_info::advanced_info::is_present() const -{ - return adv_pdb_7_0_info != 0; -} - -//Helper for advanced debug information copying -void debug_info::copy_advanced_info(const debug_info& info) -{ - free_present_advanced_info(); - - switch(info.advanced_info_type_) - { - case advanced_info_pdb_7_0: - advanced_debug_info_.adv_pdb_7_0_info = new pdb_7_0_info(*info.advanced_debug_info_.adv_pdb_7_0_info); - break; - case advanced_info_pdb_2_0: - advanced_debug_info_.adv_pdb_2_0_info = new pdb_2_0_info(*info.advanced_debug_info_.adv_pdb_2_0_info); - break; - case advanced_info_misc: - advanced_debug_info_.adv_misc_info = new misc_debug_info(*info.advanced_debug_info_.adv_misc_info); - break; - case advanced_info_coff: - advanced_debug_info_.adv_coff_info = new coff_debug_info(*info.advanced_debug_info_.adv_coff_info); - break; - default: - break; - } - - advanced_info_type_ = info.advanced_info_type_; -} - -//Helper for clearing any present advanced debug information -void debug_info::free_present_advanced_info() -{ - switch(advanced_info_type_) - { - case advanced_info_pdb_7_0: - delete advanced_debug_info_.adv_pdb_7_0_info; - break; - case advanced_info_pdb_2_0: - delete advanced_debug_info_.adv_pdb_2_0_info; - break; - case advanced_info_misc: - delete advanced_debug_info_.adv_misc_info; - break; - case advanced_info_coff: - delete advanced_debug_info_.adv_coff_info; - break; - default: - break; - } - - advanced_debug_info_.adv_pdb_7_0_info = 0; - advanced_info_type_ = advanced_info_none; -} - -//Destructor -debug_info::~debug_info() -{ - free_present_advanced_info(); -} - -//Sets advanced debug information -void debug_info::set_advanced_debug_info(const pdb_7_0_info& info) -{ - free_present_advanced_info(); - advanced_debug_info_.adv_pdb_7_0_info = new pdb_7_0_info(info); - advanced_info_type_ = advanced_info_pdb_7_0; -} - -void debug_info::set_advanced_debug_info(const pdb_2_0_info& info) -{ - free_present_advanced_info(); - advanced_debug_info_.adv_pdb_2_0_info = new pdb_2_0_info(info); - advanced_info_type_ = advanced_info_pdb_2_0; -} - -void debug_info::set_advanced_debug_info(const misc_debug_info& info) -{ - free_present_advanced_info(); - advanced_debug_info_.adv_misc_info = new misc_debug_info(info); - advanced_info_type_ = advanced_info_misc; -} - -void debug_info::set_advanced_debug_info(const coff_debug_info& info) -{ - free_present_advanced_info(); - advanced_debug_info_.adv_coff_info = new coff_debug_info(info); - advanced_info_type_ = advanced_info_coff; -} - -//Returns advanced debug information type -debug_info::advanced_info_type debug_info::get_advanced_info_type() const -{ - return advanced_info_type_; -} - -//Returns advanced debug information or throws an exception, -//if requested information type is not contained by structure -template<> -const pdb_7_0_info debug_info::get_advanced_debug_info<pdb_7_0_info>() const -{ - if(advanced_info_type_ != advanced_info_pdb_7_0) - throw pe_exception("Debug info structure does not contain PDB 7.0 data", pe_exception::advanced_debug_information_request_error); - - return *advanced_debug_info_.adv_pdb_7_0_info; -} - -template<> -const pdb_2_0_info debug_info::get_advanced_debug_info<pdb_2_0_info>() const -{ - if(advanced_info_type_ != advanced_info_pdb_2_0) - throw pe_exception("Debug info structure does not contain PDB 2.0 data", pe_exception::advanced_debug_information_request_error); - - return *advanced_debug_info_.adv_pdb_2_0_info; -} - -template<> -const misc_debug_info debug_info::get_advanced_debug_info<misc_debug_info>() const -{ - if(advanced_info_type_ != advanced_info_misc) - throw pe_exception("Debug info structure does not contain MISC data", pe_exception::advanced_debug_information_request_error); - - return *advanced_debug_info_.adv_misc_info; -} - -template<> -const coff_debug_info debug_info::get_advanced_debug_info<coff_debug_info>() const -{ - if(advanced_info_type_ != advanced_info_coff) - throw pe_exception("Debug info structure does not contain COFF data", pe_exception::advanced_debug_information_request_error); - - return *advanced_debug_info_.adv_coff_info; -} - -//Sets advanced debug information type, if no advanced info structure available -void debug_info::set_advanced_info_type(advanced_info_type type) -{ - free_present_advanced_info(); - if(advanced_info_type_ >= advanced_info_codeview_4_0) //Don't set info type for those types, which have advanced info structures - advanced_info_type_ = type; -} - -//Default constructor -pdb_7_0_info::pdb_7_0_info() - :age_(0) -{ - memset(&guid_, 0, sizeof(guid_)); -} - -//Constructor from data -pdb_7_0_info::pdb_7_0_info(const CV_INFO_PDB70* info) - :age_(info->Age), guid_(info->Signature), - pdb_file_name_(reinterpret_cast<const char*>(info->PdbFileName)) //Must be checked before for null-termination -{} - -//Returns debug PDB 7.0 structure GUID -const guid pdb_7_0_info::get_guid() const -{ - return guid_; -} - -//Returns age of build -uint32_t pdb_7_0_info::get_age() const -{ - return age_; -} - -//Returns PDB file name / path -const std::string& pdb_7_0_info::get_pdb_file_name() const -{ - return pdb_file_name_; -} - -//Default constructor -pdb_2_0_info::pdb_2_0_info() - :age_(0), signature_(0) -{} - -//Constructor from data -pdb_2_0_info::pdb_2_0_info(const CV_INFO_PDB20* info) - :age_(info->Age), signature_(info->Signature), - pdb_file_name_(reinterpret_cast<const char*>(info->PdbFileName)) //Must be checked before for null-termination -{} - -//Returns debug PDB 2.0 structure signature -uint32_t pdb_2_0_info::get_signature() const -{ - return signature_; -} - -//Returns age of build -uint32_t pdb_2_0_info::get_age() const -{ - return age_; -} - -//Returns PDB file name / path -const std::string& pdb_2_0_info::get_pdb_file_name() const -{ - return pdb_file_name_; -} - -//Default constructor -misc_debug_info::misc_debug_info() - :data_type_(0), unicode_(false) -{} - -//Constructor from data -misc_debug_info::misc_debug_info(const image_debug_misc* info) - :data_type_(info->DataType), unicode_(info->Unicode ? true : false) -{ - //IMAGE_DEBUG_MISC::Data must be checked before! - if(info->Unicode) - { -#ifdef PE_BLISS_WINDOWS - debug_data_unicode_ = std::wstring(reinterpret_cast<const wchar_t*>(info->Data), (info->Length - sizeof(image_debug_misc) + 1 /* BYTE[1] in the end of structure */) / 2); -#else - debug_data_unicode_ = pe_utils::from_ucs2(u16string(reinterpret_cast<const unicode16_t*>(info->Data), (info->Length - sizeof(image_debug_misc) + 1 /* BYTE[1] in the end of structure */) / 2)); -#endif - - pe_utils::strip_nullbytes(debug_data_unicode_); //Strip nullbytes in the end of string - } - else - { - debug_data_ansi_ = std::string(reinterpret_cast<const char*>(info->Data), info->Length - sizeof(image_debug_misc) + 1 /* BYTE[1] in the end of structure */); - pe_utils::strip_nullbytes(debug_data_ansi_); //Strip nullbytes in the end of string - } -} - -//Returns debug data type -uint32_t misc_debug_info::get_data_type() const -{ - return data_type_; -} - -//Returns true if data type is exe name -bool misc_debug_info::is_exe_name() const -{ - return data_type_ == image_debug_misc_exename; -} - -//Returns true if debug data is UNICODE -bool misc_debug_info::is_unicode() const -{ - return unicode_; -} - -//Returns debug data (ANSI) -const std::string& misc_debug_info::get_data_ansi() const -{ - return debug_data_ansi_; -} - -//Returns debug data (UNICODE) -const std::wstring& misc_debug_info::get_data_unicode() const -{ - return debug_data_unicode_; -} - -//Default constructor -coff_debug_info::coff_debug_info() - :number_of_symbols_(0), - lva_to_first_symbol_(0), - number_of_line_numbers_(0), - lva_to_first_line_number_(0), - rva_to_first_byte_of_code_(0), - rva_to_last_byte_of_code_(0), - rva_to_first_byte_of_data_(0), - rva_to_last_byte_of_data_(0) -{} - -//Constructor from data -coff_debug_info::coff_debug_info(const image_coff_symbols_header* info) - :number_of_symbols_(info->NumberOfSymbols), - lva_to_first_symbol_(info->LvaToFirstSymbol), - number_of_line_numbers_(info->NumberOfLinenumbers), - lva_to_first_line_number_(info->LvaToFirstLinenumber), - rva_to_first_byte_of_code_(info->RvaToFirstByteOfCode), - rva_to_last_byte_of_code_(info->RvaToLastByteOfCode), - rva_to_first_byte_of_data_(info->RvaToFirstByteOfData), - rva_to_last_byte_of_data_(info->RvaToLastByteOfData) -{} - -//Returns number of symbols -uint32_t coff_debug_info::get_number_of_symbols() const -{ - return number_of_symbols_; -} - -//Returns virtual address of the first symbol -uint32_t coff_debug_info::get_lva_to_first_symbol() const -{ - return lva_to_first_symbol_; -} - -//Returns number of line-number entries -uint32_t coff_debug_info::get_number_of_line_numbers() const -{ - return number_of_line_numbers_; -} - -//Returns virtual address of the first line-number entry -uint32_t coff_debug_info::get_lva_to_first_line_number() const -{ - return lva_to_first_line_number_; -} - -//Returns relative virtual address of the first byte of code -uint32_t coff_debug_info::get_rva_to_first_byte_of_code() const -{ - return rva_to_first_byte_of_code_; -} - -//Returns relative virtual address of the last byte of code -uint32_t coff_debug_info::get_rva_to_last_byte_of_code() const -{ - return rva_to_last_byte_of_code_; -} - -//Returns relative virtual address of the first byte of data -uint32_t coff_debug_info::get_rva_to_first_byte_of_data() const -{ - return rva_to_first_byte_of_data_; -} - -//Returns relative virtual address of the last byte of data -uint32_t coff_debug_info::get_rva_to_last_byte_of_data() const -{ - return rva_to_last_byte_of_data_; -} - -//Returns COFF symbols list -const coff_debug_info::coff_symbols_list& coff_debug_info::get_symbols() const -{ - return symbols_; -} - -//Adds COFF symbol -void coff_debug_info::add_symbol(const coff_symbol& sym) -{ - symbols_.push_back(sym); -} - -//Default constructor -coff_debug_info::coff_symbol::coff_symbol() - :storage_class_(0), - index_(0), - section_number_(0), rva_(0), - type_(0), - is_filename_(false) -{} - -//Returns storage class -uint32_t coff_debug_info::coff_symbol::get_storage_class() const -{ - return storage_class_; -} - -//Returns symbol index -uint32_t coff_debug_info::coff_symbol::get_index() const -{ - return index_; -} - -//Returns section number -uint32_t coff_debug_info::coff_symbol::get_section_number() const -{ - return section_number_; -} - -//Returns RVA -uint32_t coff_debug_info::coff_symbol::get_rva() const -{ - return rva_; -} - -//Returns true if structure contains file name -bool coff_debug_info::coff_symbol::is_file() const -{ - return is_filename_; -} - -//Returns text data (symbol or file name) -const std::string& coff_debug_info::coff_symbol::get_symbol() const -{ - return name_; -} - -//Sets storage class -void coff_debug_info::coff_symbol::set_storage_class(uint32_t storage_class) -{ - storage_class_ = storage_class; -} - -//Sets symbol index -void coff_debug_info::coff_symbol::set_index(uint32_t index) -{ - index_ = index; -} - -//Sets section number -void coff_debug_info::coff_symbol::set_section_number(uint32_t section_number) -{ - section_number_ = section_number; -} - -//Sets RVA -void coff_debug_info::coff_symbol::set_rva(uint32_t rva) -{ - rva_ = rva; -} - -//Sets file name -void coff_debug_info::coff_symbol::set_file_name(const std::string& file_name) -{ - name_ = file_name; - is_filename_ = true; -} - -//Sets symbol name -void coff_debug_info::coff_symbol::set_symbol_name(const std::string& symbol_name) -{ - name_ = symbol_name; - is_filename_ = false; -} - -//Returns type -uint16_t coff_debug_info::coff_symbol::get_type() const -{ - return type_; -} - -//Sets type -void coff_debug_info::coff_symbol::set_type(uint16_t type) -{ - type_ = type; -} - -//Returns debug information list -const debug_info_list get_debug_information(const pe_base& pe) -{ - debug_info_list ret; - - //If there's no debug directory, return empty list - if(!pe.has_debug()) - return ret; - - //Check the length in bytes of the section containing debug directory - if(pe.section_data_length_from_rva(pe.get_directory_rva(image_directory_entry_debug), pe.get_directory_rva(image_directory_entry_debug), section_data_virtual, true) - < sizeof(image_debug_directory)) - throw pe_exception("Incorrect debug directory", pe_exception::incorrect_debug_directory); - - unsigned long current_pos = pe.get_directory_rva(image_directory_entry_debug); - - //First IMAGE_DEBUG_DIRECTORY table - image_debug_directory directory = pe.section_data_from_rva<image_debug_directory>(current_pos, section_data_virtual, true); - - if(!pe_utils::is_sum_safe(pe.get_directory_rva(image_directory_entry_debug), pe.get_directory_size(image_directory_entry_debug))) - throw pe_exception("Incorrect debug directory", pe_exception::incorrect_debug_directory); - - //Iterate over all IMAGE_DEBUG_DIRECTORY directories - while(directory.PointerToRawData - && current_pos < pe.get_directory_rva(image_directory_entry_debug) + pe.get_directory_size(image_directory_entry_debug)) - { - //Create debug information structure - debug_info info(directory); - - //Find raw debug data - const pe_base::debug_data_list& debug_datas = pe.get_raw_debug_data_list(); - pe_base::debug_data_list::const_iterator it = debug_datas.find(directory.PointerToRawData); - if(it != debug_datas.end()) //If it exists, we'll do some detailed debug info research - { - const std::string& debug_data = (*it).second; - switch(directory.Type) - { - case image_debug_type_coff: - { - //Check data length - if(debug_data.length() < sizeof(image_coff_symbols_header)) - throw pe_exception("Incorrect debug directory", pe_exception::incorrect_debug_directory); - - //Get coff header structure pointer - const image_coff_symbols_header* coff = reinterpret_cast<const image_coff_symbols_header*>(debug_data.data()); - - //Check possible overflows - if(coff->NumberOfSymbols >= pe_utils::max_dword / sizeof(image_symbol) - || !pe_utils::is_sum_safe(coff->NumberOfSymbols * sizeof(image_symbol), coff->LvaToFirstSymbol)) - throw pe_exception("Incorrect debug directory", pe_exception::incorrect_debug_directory); - - //Check data length again - if(debug_data.length() < coff->NumberOfSymbols * sizeof(image_symbol) + coff->LvaToFirstSymbol) - throw pe_exception("Incorrect debug directory", pe_exception::incorrect_debug_directory); - - //Create COFF debug info structure - coff_debug_info coff_info(coff); - - //Enumerate debug symbols data - for(uint32_t i = 0; i < coff->NumberOfSymbols; ++i) - { - //Safe sum (checked above) - const image_symbol* sym = reinterpret_cast<const image_symbol*>(debug_data.data() + i * sizeof(image_symbol) + coff->LvaToFirstSymbol); - - coff_debug_info::coff_symbol symbol; - symbol.set_index(i); //Save symbol index - symbol.set_storage_class(sym->StorageClass); //Save storage class - symbol.set_type(sym->Type); //Save storage class - - //Check data length again - if(!pe_utils::is_sum_safe(i, sym->NumberOfAuxSymbols) - || (i + sym->NumberOfAuxSymbols) > coff->NumberOfSymbols - || debug_data.length() < (i + 1) * sizeof(image_symbol) + coff->LvaToFirstSymbol + sym->NumberOfAuxSymbols * sizeof(image_symbol)) - throw pe_exception("Incorrect debug directory", pe_exception::incorrect_debug_directory); - - //If symbol is filename - if(sym->StorageClass == image_sym_class_file) - { - //Save file name, it is situated just after this IMAGE_SYMBOL structure - std::string file_name(reinterpret_cast<const char*>(debug_data.data() + (i + 1) * sizeof(image_symbol)), sym->NumberOfAuxSymbols * sizeof(image_symbol)); - pe_utils::strip_nullbytes(file_name); - symbol.set_file_name(file_name); - - //Save symbol info - coff_info.add_symbol(symbol); - - //Move to next symbol - i += sym->NumberOfAuxSymbols; - continue; - } - - //Dump some other symbols - if(((sym->StorageClass == image_sym_class_static) - && (sym->NumberOfAuxSymbols == 0) - && (sym->SectionNumber == 1)) - || - ((sym->StorageClass == image_sym_class_external) - && ISFCN(sym->Type) - && (sym->SectionNumber > 0)) - ) - { - //Save RVA and section number - symbol.set_section_number(sym->SectionNumber); - symbol.set_rva(sym->Value); - - //If symbol has short name - if(sym->N.Name.Short) - { - //Copy and save symbol name - char name_buff[9]; - memcpy(name_buff, sym->N.ShortName, 8); - name_buff[8] = '\0'; - symbol.set_symbol_name(name_buff); - } - else - { - //Symbol has long name - - //Check possible overflows - if(!pe_utils::is_sum_safe(coff->LvaToFirstSymbol + coff->NumberOfSymbols * sizeof(image_symbol), sym->N.Name.Long)) - throw pe_exception("Incorrect debug directory", pe_exception::incorrect_debug_directory); - - //Here we have an offset to the string table - uint32_t symbol_offset = coff->LvaToFirstSymbol + coff->NumberOfSymbols * sizeof(image_symbol) + sym->N.Name.Long; - - //Check data length - if(debug_data.length() < symbol_offset) - throw pe_exception("Incorrect debug directory", pe_exception::incorrect_debug_directory); - - //Check symbol name for null-termination - if(!pe_utils::is_null_terminated(debug_data.data() + symbol_offset, debug_data.length() - symbol_offset)) - throw pe_exception("Incorrect debug directory", pe_exception::incorrect_debug_directory); - - //Save symbol name - symbol.set_symbol_name(debug_data.data() + symbol_offset); - } - - //Save symbol info - coff_info.add_symbol(symbol); - - //Move to next symbol - i += sym->NumberOfAuxSymbols; - continue; - } - } - - info.set_advanced_debug_info(coff_info); - } - break; - - case image_debug_type_codeview: - { - //Check data length - if(debug_data.length() < sizeof(OMFSignature*)) - throw pe_exception("Incorrect debug directory", pe_exception::incorrect_debug_directory); - - //Get POMFSignature structure pointer from the very beginning of debug data - const OMFSignature* sig = reinterpret_cast<const OMFSignature*>(debug_data.data()); - if(!memcmp(sig->Signature, "RSDS", 4)) - { - //Signature is "RSDS" - PDB 7.0 - - //Check data length - if(debug_data.length() < sizeof(CV_INFO_PDB70)) - throw pe_exception("Incorrect debug directory", pe_exception::incorrect_debug_directory); - - const CV_INFO_PDB70* pdb_data = reinterpret_cast<const CV_INFO_PDB70*>(debug_data.data()); - - //Check PDB file name null-termination - if(!pe_utils::is_null_terminated(pdb_data->PdbFileName, debug_data.length() - (sizeof(CV_INFO_PDB70) - 1 /* BYTE of filename in structure */))) - throw pe_exception("Incorrect debug directory", pe_exception::incorrect_debug_directory); - - info.set_advanced_debug_info(pdb_7_0_info(pdb_data)); - } - else if(!memcmp(sig->Signature, "NB10", 4)) - { - //Signature is "NB10" - PDB 2.0 - - //Check data length - if(debug_data.length() < sizeof(CV_INFO_PDB20)) - throw pe_exception("Incorrect debug directory", pe_exception::incorrect_debug_directory); - - const CV_INFO_PDB20* pdb_data = reinterpret_cast<const CV_INFO_PDB20*>(debug_data.data()); - - //Check PDB file name null-termination - if(!pe_utils::is_null_terminated(pdb_data->PdbFileName, debug_data.length() - (sizeof(CV_INFO_PDB20) - 1 /* BYTE of filename in structure */))) - throw pe_exception("Incorrect debug directory", pe_exception::incorrect_debug_directory); - - info.set_advanced_debug_info(pdb_2_0_info(pdb_data)); - } - else if(!memcmp(sig->Signature, "NB09", 4)) - { - //CodeView 4.0, no structures available - info.set_advanced_info_type(debug_info::advanced_info_codeview_4_0); - } - else if(!memcmp(sig->Signature, "NB11", 4)) - { - //CodeView 5.0, no structures available - info.set_advanced_info_type(debug_info::advanced_info_codeview_5_0); - } - else if(!memcmp(sig->Signature, "NB05", 4)) - { - //Other CodeView, no structures available - info.set_advanced_info_type(debug_info::advanced_info_codeview); - } - } - - break; - - case image_debug_type_misc: - { - //Check data length - if(debug_data.length() < sizeof(image_debug_misc)) - throw pe_exception("Incorrect debug directory", pe_exception::incorrect_debug_directory); - - //Get misc structure pointer - const image_debug_misc* misc_data = reinterpret_cast<const image_debug_misc*>(debug_data.data()); - - //Check misc data length - if(debug_data.length() < misc_data->Length /* Total length of record */) - throw pe_exception("Incorrect debug directory", pe_exception::incorrect_debug_directory); - - //Save advanced information - info.set_advanced_debug_info(misc_debug_info(misc_data)); - } - break; - } - } - - //Save debug information structure - ret.push_back(info); - - //Check possible overflow - if(!pe_utils::is_sum_safe(current_pos, sizeof(image_debug_directory))) - throw pe_exception("Incorrect debug directory", pe_exception::incorrect_debug_directory); - - //Go to next debug entry - current_pos += sizeof(image_debug_directory); - directory = pe.section_data_from_rva<image_debug_directory>(current_pos, section_data_virtual, true); - } - - return ret; -} -} diff --git a/tools/pe_bliss/pe_debug.h b/tools/pe_bliss/pe_debug.h deleted file mode 100644 index 73a7e6860d..0000000000 --- a/tools/pe_bliss/pe_debug.h +++ /dev/null @@ -1,324 +0,0 @@ -/*************************************************************************/ -/* Copyright (c) 2015 dx, http://kaimi.ru */ -/* */ -/* Permission is hereby granted, free of charge, to any person */ -/* obtaining a copy of this software and associated documentation */ -/* files (the "Software"), to deal in the Software without */ -/* restriction, including without limitation the rights to use, */ -/* copy, modify, merge, publish, distribute, sublicense, and/or */ -/* sell copies of the Software, and to permit persons to whom the */ -/* Software is furnished to do so, subject to the following conditions: */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#pragma once -#include <vector> -#include "pe_structures.h" -#include "pe_base.h" - -namespace pe_bliss -{ -//Class representing advanced RSDS (PDB 7.0) information -class pdb_7_0_info -{ -public: - //Default constructor - pdb_7_0_info(); - //Constructor from data - explicit pdb_7_0_info(const pe_win::CV_INFO_PDB70* info); - - //Returns debug PDB 7.0 structure GUID - const pe_win::guid get_guid() const; - //Returns age of build - uint32_t get_age() const; - //Returns PDB file name / path - const std::string& get_pdb_file_name() const; - -private: - uint32_t age_; - pe_win::guid guid_; - std::string pdb_file_name_; -}; - -//Class representing advanced NB10 (PDB 2.0) information -class pdb_2_0_info -{ -public: - //Default constructor - pdb_2_0_info(); - //Constructor from data - explicit pdb_2_0_info(const pe_win::CV_INFO_PDB20* info); - - //Returns debug PDB 2.0 structure signature - uint32_t get_signature() const; - //Returns age of build - uint32_t get_age() const; - //Returns PDB file name / path - const std::string& get_pdb_file_name() const; - -private: - uint32_t age_; - uint32_t signature_; - std::string pdb_file_name_; -}; - -//Class representing advanced misc (IMAGE_DEBUG_TYPE_MISC) info -class misc_debug_info -{ -public: - //Default constructor - misc_debug_info(); - //Constructor from data - explicit misc_debug_info(const pe_win::image_debug_misc* info); - - //Returns debug data type - uint32_t get_data_type() const; - //Returns true if data type is exe name - bool is_exe_name() const; - - //Returns true if debug data is UNICODE - bool is_unicode() const; - //Returns debug data (ANSI or UNICODE) - const std::string& get_data_ansi() const; - const std::wstring& get_data_unicode() const; - -private: - uint32_t data_type_; - bool unicode_; - std::string debug_data_ansi_; - std::wstring debug_data_unicode_; -}; - -//Class representing COFF (IMAGE_DEBUG_TYPE_COFF) debug info -class coff_debug_info -{ -public: - //Structure representing COFF symbol - struct coff_symbol - { - public: - //Default constructor - coff_symbol(); - - //Returns storage class - uint32_t get_storage_class() const; - //Returns symbol index - uint32_t get_index() const; - //Returns section number - uint32_t get_section_number() const; - //Returns RVA - uint32_t get_rva() const; - //Returns type - uint16_t get_type() const; - - //Returns true if structure contains file name - bool is_file() const; - //Returns text data (symbol or file name) - const std::string& get_symbol() const; - - public: //These functions do not change everything inside image, they are used by PE class - //Sets storage class - void set_storage_class(uint32_t storage_class); - //Sets symbol index - void set_index(uint32_t index); - //Sets section number - void set_section_number(uint32_t section_number); - //Sets RVA - void set_rva(uint32_t rva); - //Sets type - void set_type(uint16_t type); - - //Sets file name - void set_file_name(const std::string& file_name); - //Sets symbol name - void set_symbol_name(const std::string& symbol_name); - - private: - uint32_t storage_class_; - uint32_t index_; - uint32_t section_number_, rva_; - uint16_t type_; - bool is_filename_; - std::string name_; - }; - -public: - typedef std::vector<coff_symbol> coff_symbols_list; - -public: - //Default constructor - coff_debug_info(); - //Constructor from data - explicit coff_debug_info(const pe_win::image_coff_symbols_header* info); - - //Returns number of symbols - uint32_t get_number_of_symbols() const; - //Returns virtual address of the first symbol - uint32_t get_lva_to_first_symbol() const; - //Returns number of line-number entries - uint32_t get_number_of_line_numbers() const; - //Returns virtual address of the first line-number entry - uint32_t get_lva_to_first_line_number() const; - //Returns relative virtual address of the first byte of code - uint32_t get_rva_to_first_byte_of_code() const; - //Returns relative virtual address of the last byte of code - uint32_t get_rva_to_last_byte_of_code() const; - //Returns relative virtual address of the first byte of data - uint32_t get_rva_to_first_byte_of_data() const; - //Returns relative virtual address of the last byte of data - uint32_t get_rva_to_last_byte_of_data() const; - - //Returns COFF symbols list - const coff_symbols_list& get_symbols() const; - -public: //These functions do not change everything inside image, they are used by PE class - //Adds COFF symbol - void add_symbol(const coff_symbol& sym); - -private: - uint32_t number_of_symbols_; - uint32_t lva_to_first_symbol_; - uint32_t number_of_line_numbers_; - uint32_t lva_to_first_line_number_; - uint32_t rva_to_first_byte_of_code_; - uint32_t rva_to_last_byte_of_code_; - uint32_t rva_to_first_byte_of_data_; - uint32_t rva_to_last_byte_of_data_; - -private: - coff_symbols_list symbols_; -}; - -//Class representing debug information -class debug_info -{ -public: - //Enumeration of debug information types - enum debug_info_type - { - debug_type_unknown, - debug_type_coff, - debug_type_codeview, - debug_type_fpo, - debug_type_misc, - debug_type_exception, - debug_type_fixup, - debug_type_omap_to_src, - debug_type_omap_from_src, - debug_type_borland, - debug_type_reserved10, - debug_type_clsid - }; - -public: - //Enumeration of advanced debug information types - enum advanced_info_type - { - advanced_info_none, //No advanced info - advanced_info_pdb_7_0, //PDB 7.0 - advanced_info_pdb_2_0, //PDB 2.0 - advanced_info_misc, //MISC debug info - advanced_info_coff, //COFF debug info - //No advanced info structures available for types below - advanced_info_codeview_4_0, //CodeView 4.0 - advanced_info_codeview_5_0, //CodeView 5.0 - advanced_info_codeview //CodeView - }; - -public: - //Default constructor - debug_info(); - //Constructor from data - explicit debug_info(const pe_win::image_debug_directory& debug); - //Copy constructor - debug_info(const debug_info& info); - //Copy assignment operator - debug_info& operator=(const debug_info& info); - //Destructor - ~debug_info(); - - //Returns debug characteristics - uint32_t get_characteristics() const; - //Returns debug datetimestamp - uint32_t get_time_stamp() const; - //Returns major version - uint32_t get_major_version() const; - //Returns minor version - uint32_t get_minor_version() const; - //Returns type of debug info (unchecked) - uint32_t get_type_raw() const; - //Returns type of debug info from debug_info_type enumeration - debug_info_type get_type() const; - //Returns size of debug data (internal, .pdb or other file doesn't count) - uint32_t get_size_of_data() const; - //Returns RVA of debug info when mapped to memory or zero, if info is not mapped - uint32_t get_rva_of_raw_data() const; - //Returns raw file pointer to raw data - uint32_t get_pointer_to_raw_data() const; - - //Returns advanced debug information type - advanced_info_type get_advanced_info_type() const; - //Returns advanced debug information or throws an exception, - //if requested information type is not contained by structure - template<typename AdvancedInfo> - const AdvancedInfo get_advanced_debug_info() const; - -public: //These functions do not change everything inside image, they are used by PE class - //Sets advanced debug information - void set_advanced_debug_info(const pdb_7_0_info& info); - void set_advanced_debug_info(const pdb_2_0_info& info); - void set_advanced_debug_info(const misc_debug_info& info); - void set_advanced_debug_info(const coff_debug_info& info); - - //Sets advanced debug information type, if no advanced info structure available - void set_advanced_info_type(advanced_info_type type); - -private: - uint32_t characteristics_; - uint32_t time_stamp_; - uint32_t major_version_, minor_version_; - uint32_t type_; - uint32_t size_of_data_; - uint32_t address_of_raw_data_; //RVA when mapped or 0 - uint32_t pointer_to_raw_data_; //RAW file offset - - //Union containing advanced debug information pointer - union advanced_info - { - public: - //Default constructor - advanced_info(); - - //Returns true if advanced debug info is present - bool is_present() const; - - public: - pdb_7_0_info* adv_pdb_7_0_info; - pdb_2_0_info* adv_pdb_2_0_info; - misc_debug_info* adv_misc_info; - coff_debug_info* adv_coff_info; - }; - - //Helper for advanced debug information copying - void copy_advanced_info(const debug_info& info); - //Helper for clearing any present advanced debug information - void free_present_advanced_info(); - - advanced_info advanced_debug_info_; - //Advanced information type - advanced_info_type advanced_info_type_; -}; - -typedef std::vector<debug_info> debug_info_list; - -//Returns debug information list -const debug_info_list get_debug_information(const pe_base& pe); -} diff --git a/tools/pe_bliss/pe_directory.cpp b/tools/pe_bliss/pe_directory.cpp deleted file mode 100644 index 13ad2afc5d..0000000000 --- a/tools/pe_bliss/pe_directory.cpp +++ /dev/null @@ -1,59 +0,0 @@ -/*************************************************************************/ -/* Copyright (c) 2015 dx, http://kaimi.ru */ -/* */ -/* Permission is hereby granted, free of charge, to any person */ -/* obtaining a copy of this software and associated documentation */ -/* files (the "Software"), to deal in the Software without */ -/* restriction, including without limitation the rights to use, */ -/* copy, modify, merge, publish, distribute, sublicense, and/or */ -/* sell copies of the Software, and to permit persons to whom the */ -/* Software is furnished to do so, subject to the following conditions: */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#include "pe_directory.h" - -namespace pe_bliss -{ -//Default constructor -image_directory::image_directory() - :rva_(0), size_(0) -{} - -//Constructor from data -image_directory::image_directory(uint32_t rva, uint32_t size) - :rva_(rva), size_(size) -{} - -//Returns RVA -uint32_t image_directory::get_rva() const -{ - return rva_; -} - -//Returns size -uint32_t image_directory::get_size() const -{ - return size_; -} - -//Sets RVA -void image_directory::set_rva(uint32_t rva) -{ - rva_ = rva; -} - -//Sets size -void image_directory::set_size(uint32_t size) -{ - size_ = size; -} -} diff --git a/tools/pe_bliss/pe_directory.h b/tools/pe_bliss/pe_directory.h deleted file mode 100644 index a7b1ea7a5f..0000000000 --- a/tools/pe_bliss/pe_directory.h +++ /dev/null @@ -1,50 +0,0 @@ -/*************************************************************************/ -/* Copyright (c) 2015 dx, http://kaimi.ru */ -/* */ -/* Permission is hereby granted, free of charge, to any person */ -/* obtaining a copy of this software and associated documentation */ -/* files (the "Software"), to deal in the Software without */ -/* restriction, including without limitation the rights to use, */ -/* copy, modify, merge, publish, distribute, sublicense, and/or */ -/* sell copies of the Software, and to permit persons to whom the */ -/* Software is furnished to do so, subject to the following conditions: */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#pragma once -#include "stdint_defs.h" - -namespace pe_bliss -{ -//Class representing image directory data -class image_directory -{ -public: - //Default constructor - image_directory(); - //Constructor from data - image_directory(uint32_t rva, uint32_t size); - - //Returns RVA - uint32_t get_rva() const; - //Returns size - uint32_t get_size() const; - - //Sets RVA - void set_rva(uint32_t rva); - //Sets size - void set_size(uint32_t size); - -private: - uint32_t rva_; - uint32_t size_; -}; -} diff --git a/tools/pe_bliss/pe_dotnet.cpp b/tools/pe_bliss/pe_dotnet.cpp deleted file mode 100644 index f34a76eae8..0000000000 --- a/tools/pe_bliss/pe_dotnet.cpp +++ /dev/null @@ -1,186 +0,0 @@ -/*************************************************************************/ -/* Copyright (c) 2015 dx, http://kaimi.ru */ -/* */ -/* Permission is hereby granted, free of charge, to any person */ -/* obtaining a copy of this software and associated documentation */ -/* files (the "Software"), to deal in the Software without */ -/* restriction, including without limitation the rights to use, */ -/* copy, modify, merge, publish, distribute, sublicense, and/or */ -/* sell copies of the Software, and to permit persons to whom the */ -/* Software is furnished to do so, subject to the following conditions: */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#include <string.h> -#include "pe_dotnet.h" - -namespace pe_bliss -{ -using namespace pe_win; - -//.NET -basic_dotnet_info::basic_dotnet_info() -{ - memset(&header_, 0, sizeof(header_)); -} - -//Constructor from data -basic_dotnet_info::basic_dotnet_info(const image_cor20_header& header) - :header_(header) -{} - -//Returns major runtime version -uint16_t basic_dotnet_info::get_major_runtime_version() const -{ - return header_.MajorRuntimeVersion; -} - -//Returns minor runtime version -uint16_t basic_dotnet_info::get_minor_runtime_version() const -{ - return header_.MinorRuntimeVersion; -} - -//Returns RVA of metadata (symbol table and startup information) -uint32_t basic_dotnet_info::get_rva_of_metadata() const -{ - return header_.MetaData.VirtualAddress; -} - -//Returns size of metadata (symbol table and startup information) -uint32_t basic_dotnet_info::get_size_of_metadata() const -{ - return header_.MetaData.Size; -} - -//Returns flags -uint32_t basic_dotnet_info::get_flags() const -{ - return header_.Flags; -} - -//Returns true if entry point is native -bool basic_dotnet_info::is_native_entry_point() const -{ - return (header_.Flags & comimage_flags_native_entrypoint) ? true : false; -} - -//Returns true if 32 bit required -bool basic_dotnet_info::is_32bit_required() const -{ - return (header_.Flags & comimage_flags_32bitrequired) ? true : false; -} - -//Returns true if image is IL library -bool basic_dotnet_info::is_il_library() const -{ - return (header_.Flags & comimage_flags_il_library) ? true : false; -} - -//Returns true if image uses IL only -bool basic_dotnet_info::is_il_only() const -{ - return (header_.Flags & comimage_flags_ilonly) ? true : false; -} - -//Returns entry point RVA (if entry point is native) -//Returns entry point managed token (if entry point is managed) -uint32_t basic_dotnet_info::get_entry_point_rva_or_token() const -{ - return header_.EntryPointToken; -} - -//Returns RVA of managed resources -uint32_t basic_dotnet_info::get_rva_of_resources() const -{ - return header_.Resources.VirtualAddress; -} - -//Returns size of managed resources -uint32_t basic_dotnet_info::get_size_of_resources() const -{ - return header_.Resources.Size; -} - -//Returns RVA of strong name signature -uint32_t basic_dotnet_info::get_rva_of_strong_name_signature() const -{ - return header_.StrongNameSignature.VirtualAddress; -} - -//Returns size of strong name signature -uint32_t basic_dotnet_info::get_size_of_strong_name_signature() const -{ - return header_.StrongNameSignature.Size; -} - -//Returns RVA of code manager table -uint32_t basic_dotnet_info::get_rva_of_code_manager_table() const -{ - return header_.CodeManagerTable.VirtualAddress; -} - -//Returns size of code manager table -uint32_t basic_dotnet_info::get_size_of_code_manager_table() const -{ - return header_.CodeManagerTable.Size; -} - -//Returns RVA of VTable fixups -uint32_t basic_dotnet_info::get_rva_of_vtable_fixups() const -{ - return header_.VTableFixups.VirtualAddress; -} - -//Returns size of VTable fixups -uint32_t basic_dotnet_info::get_size_of_vtable_fixups() const -{ - return header_.VTableFixups.Size; -} - -//Returns RVA of export address table jumps -uint32_t basic_dotnet_info::get_rva_of_export_address_table_jumps() const -{ - return header_.ExportAddressTableJumps.VirtualAddress; -} - -//Returns size of export address table jumps -uint32_t basic_dotnet_info::get_size_of_export_address_table_jumps() const -{ - return header_.ExportAddressTableJumps.Size; -} - -//Returns RVA of managed native header -//(precompiled header info, usually set to zero, for internal use) -uint32_t basic_dotnet_info::get_rva_of_managed_native_header() const -{ - return header_.ManagedNativeHeader.VirtualAddress; -} - -//Returns size of managed native header -//(precompiled header info, usually set to zero, for internal use) -uint32_t basic_dotnet_info::get_size_of_managed_native_header() const -{ - return header_.ManagedNativeHeader.Size; -} - -//Returns basic .NET information -//If image is not native, throws an exception -const basic_dotnet_info get_basic_dotnet_info(const pe_base& pe) -{ - //If there's no debug directory, return empty list - if(!pe.is_dotnet()) - throw pe_exception("Image does not have managed code", pe_exception::image_does_not_have_managed_code); - - //Return basic .NET information - return basic_dotnet_info(pe.section_data_from_rva<image_cor20_header>(pe.get_directory_rva(image_directory_entry_com_descriptor), section_data_virtual, true)); -} -} diff --git a/tools/pe_bliss/pe_dotnet.h b/tools/pe_bliss/pe_dotnet.h deleted file mode 100644 index 96b0ac7d0a..0000000000 --- a/tools/pe_bliss/pe_dotnet.h +++ /dev/null @@ -1,97 +0,0 @@ -/*************************************************************************/ -/* Copyright (c) 2015 dx, http://kaimi.ru */ -/* */ -/* Permission is hereby granted, free of charge, to any person */ -/* obtaining a copy of this software and associated documentation */ -/* files (the "Software"), to deal in the Software without */ -/* restriction, including without limitation the rights to use, */ -/* copy, modify, merge, publish, distribute, sublicense, and/or */ -/* sell copies of the Software, and to permit persons to whom the */ -/* Software is furnished to do so, subject to the following conditions: */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#pragma once -#include "pe_structures.h" -#include "pe_base.h" - -namespace pe_bliss -{ -//Class representing basic .NET header information -class basic_dotnet_info -{ -public: - //Default constructor - basic_dotnet_info(); - //Constructor from data - explicit basic_dotnet_info(const pe_win::image_cor20_header& header); - - //Returns major runtime version - uint16_t get_major_runtime_version() const; - //Returns minor runtime version - uint16_t get_minor_runtime_version() const; - - //Returns RVA of metadata (symbol table and startup information) - uint32_t get_rva_of_metadata() const; - //Returns size of metadata (symbol table and startup information) - uint32_t get_size_of_metadata() const; - - //Returns flags - uint32_t get_flags() const; - - //Returns true if entry point is native - bool is_native_entry_point() const; - //Returns true if 32 bit required - bool is_32bit_required() const; - //Returns true if image is IL library - bool is_il_library() const; - //Returns true if image uses IL only - bool is_il_only() const; - - //Returns entry point RVA (if entry point is native) - //Returns entry point managed token (if entry point is managed) - uint32_t get_entry_point_rva_or_token() const; - - //Returns RVA of managed resources - uint32_t get_rva_of_resources() const; - //Returns size of managed resources - uint32_t get_size_of_resources() const; - //Returns RVA of strong name signature - uint32_t get_rva_of_strong_name_signature() const; - //Returns size of strong name signature - uint32_t get_size_of_strong_name_signature() const; - //Returns RVA of code manager table - uint32_t get_rva_of_code_manager_table() const; - //Returns size of code manager table - uint32_t get_size_of_code_manager_table() const; - //Returns RVA of VTable fixups - uint32_t get_rva_of_vtable_fixups() const; - //Returns size of VTable fixups - uint32_t get_size_of_vtable_fixups() const; - //Returns RVA of export address table jumps - uint32_t get_rva_of_export_address_table_jumps() const; - //Returns size of export address table jumps - uint32_t get_size_of_export_address_table_jumps() const; - //Returns RVA of managed native header - //(precompiled header info, usually set to zero, for internal use) - uint32_t get_rva_of_managed_native_header() const; - //Returns size of managed native header - //(precompiled header info, usually set to zero, for internal use) - uint32_t get_size_of_managed_native_header() const; - -private: - pe_win::image_cor20_header header_; -}; - -//Returns basic .NET information -//If image is not native, throws an exception -const basic_dotnet_info get_basic_dotnet_info(const pe_base& pe); -} diff --git a/tools/pe_bliss/pe_exception.cpp b/tools/pe_bliss/pe_exception.cpp deleted file mode 100644 index 3161f93599..0000000000 --- a/tools/pe_bliss/pe_exception.cpp +++ /dev/null @@ -1,40 +0,0 @@ -/*************************************************************************/ -/* Copyright (c) 2015 dx, http://kaimi.ru */ -/* */ -/* Permission is hereby granted, free of charge, to any person */ -/* obtaining a copy of this software and associated documentation */ -/* files (the "Software"), to deal in the Software without */ -/* restriction, including without limitation the rights to use, */ -/* copy, modify, merge, publish, distribute, sublicense, and/or */ -/* sell copies of the Software, and to permit persons to whom the */ -/* Software is furnished to do so, subject to the following conditions: */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#include "pe_exception.h" - -namespace pe_bliss -{ -//PE exception class constructors -pe_exception::pe_exception(const char* text, exception_id id) - :std::runtime_error(text), id_(id) -{} - -pe_exception::pe_exception(const std::string& text, exception_id id) - :std::runtime_error(text), id_(id) -{} - -//Returns exception ID -pe_exception::exception_id pe_exception::get_id() const -{ - return id_; -} -} diff --git a/tools/pe_bliss/pe_exception.h b/tools/pe_bliss/pe_exception.h deleted file mode 100644 index 2b58a95772..0000000000 --- a/tools/pe_bliss/pe_exception.h +++ /dev/null @@ -1,130 +0,0 @@ -/*************************************************************************/ -/* Copyright (c) 2015 dx, http://kaimi.ru */ -/* */ -/* Permission is hereby granted, free of charge, to any person */ -/* obtaining a copy of this software and associated documentation */ -/* files (the "Software"), to deal in the Software without */ -/* restriction, including without limitation the rights to use, */ -/* copy, modify, merge, publish, distribute, sublicense, and/or */ -/* sell copies of the Software, and to permit persons to whom the */ -/* Software is furnished to do so, subject to the following conditions: */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#pragma once -#include <exception> -#include <stdexcept> - -namespace pe_bliss -{ -//PE exception class -class pe_exception : public std::runtime_error -{ -public: - //Exception IDs - enum exception_id - { - unknown_error, - bad_pe_file, - bad_dos_header, - image_nt_headers_not_found, - error_reading_image_nt_headers, - error_reading_data_directories, - error_reading_file, - pe_signature_incorrect, - incorrect_number_of_rva_and_sizes, - error_changing_section_virtual_size, - section_number_incorrect, - section_table_incorrect, - incorrect_section_alignment, - incorrect_file_alignment, - incorrect_size_of_image, - incorrect_size_of_headers, - image_section_headers_not_found, - zero_section_sizes, - section_incorrect_addr_or_size, - section_not_found, - image_section_data_not_found, - no_section_found, - image_section_table_incorrect, - directory_does_not_exist, - rva_not_exists, - error_reading_section_header, - error_reading_overlay, - incorrect_address_conversion, - - incorrect_export_directory, - incorrect_import_directory, - incorrect_relocation_directory, - incorrect_tls_directory, - incorrect_config_directory, - incorrect_bound_import_directory, - incorrect_resource_directory, - incorrect_exception_directory, - incorrect_debug_directory, - - resource_directory_entry_error, - resource_directory_entry_not_found, - resource_data_entry_not_found, - resource_incorrect_bitmap, - resource_incorrect_icon, - resource_incorrect_cursor, - resource_incorrect_string_table, - resource_string_not_found, - resource_incorrect_message_table, - resource_incorrect_version_info, - - advanced_debug_information_request_error, - image_does_not_have_managed_code, - - section_is_empty, - data_is_empty, - stream_is_bad, - - section_is_not_attached, - insufficient_space, - - cannot_rebase_relocations, - - exports_list_is_empty, - duplicate_exported_function_ordinal, - duplicate_exported_function_name, - - version_info_string_does_not_exist, - - no_more_sections_can_be_added, - - no_icon_group_found, - no_cursor_group_found, - - encoding_convertion_error, - - error_expanding_section, - - cannot_rebuild_image - }; - -public: - //Class constructors - explicit pe_exception(const char* text, exception_id id = unknown_error); - explicit pe_exception(const std::string& text, exception_id id = unknown_error); - - //Returns exception ID from exception_id enumeration - exception_id get_id() const; - - //Destructor - virtual ~pe_exception() throw() - {} - -private: - exception_id id_; -}; -} diff --git a/tools/pe_bliss/pe_exception_directory.cpp b/tools/pe_bliss/pe_exception_directory.cpp deleted file mode 100644 index 1813f02021..0000000000 --- a/tools/pe_bliss/pe_exception_directory.cpp +++ /dev/null @@ -1,177 +0,0 @@ -/*************************************************************************/ -/* Copyright (c) 2015 dx, http://kaimi.ru */ -/* */ -/* Permission is hereby granted, free of charge, to any person */ -/* obtaining a copy of this software and associated documentation */ -/* files (the "Software"), to deal in the Software without */ -/* restriction, including without limitation the rights to use, */ -/* copy, modify, merge, publish, distribute, sublicense, and/or */ -/* sell copies of the Software, and to permit persons to whom the */ -/* Software is furnished to do so, subject to the following conditions: */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#include "pe_exception_directory.h" - -namespace pe_bliss -{ -using namespace pe_win; - -//EXCEPTION DIRECTORY (exists on PE+ only) -//Default constructor -exception_entry::exception_entry() - :begin_address_(0), end_address_(0), unwind_info_address_(0), - unwind_info_version_(0), - flags_(0), - size_of_prolog_(0), - count_of_codes_(0), - frame_register_(0), - frame_offset_(0) -{} - -//Constructor from data -exception_entry::exception_entry(const image_runtime_function_entry& entry, const unwind_info& unwind_info) - :begin_address_(entry.BeginAddress), end_address_(entry.EndAddress), unwind_info_address_(entry.UnwindInfoAddress), - unwind_info_version_(unwind_info.Version), - flags_(unwind_info.Flags), - size_of_prolog_(unwind_info.SizeOfProlog), - count_of_codes_(unwind_info.CountOfCodes), - frame_register_(unwind_info.FrameRegister), - frame_offset_(unwind_info.FrameOffset) -{} - -//Returns starting address of function, affected by exception unwinding -uint32_t exception_entry::get_begin_address() const -{ - return begin_address_; -} - -//Returns ending address of function, affected by exception unwinding -uint32_t exception_entry::get_end_address() const -{ - return end_address_; -} - -//Returns unwind info address -uint32_t exception_entry::get_unwind_info_address() const -{ - return unwind_info_address_; -} - -//Returns UNWIND_INFO structure version -uint8_t exception_entry::get_unwind_info_version() const -{ - return unwind_info_version_; -} - -//Returns unwind info flags -uint8_t exception_entry::get_flags() const -{ - return flags_; -} - -//The function has an exception handler that should be called -//when looking for functions that need to examine exceptions -bool exception_entry::has_exception_handler() const -{ - return (flags_ & unw_flag_ehandler) ? true : false; -} - -//The function has a termination handler that should be called -//when unwinding an exception -bool exception_entry::has_termination_handler() const -{ - return (flags_ & unw_flag_uhandler) ? true : false; -} - -//The unwind info structure is not the primary one for the procedure -bool exception_entry::is_chaininfo() const -{ - return (flags_ & unw_flag_chaininfo) ? true : false; -} - -//Returns size of function prolog -uint8_t exception_entry::get_size_of_prolog() const -{ - return size_of_prolog_; -} - -//Returns number of unwind slots -uint8_t exception_entry::get_number_of_unwind_slots() const -{ - return count_of_codes_; -} - -//If the function uses frame pointer -bool exception_entry::uses_frame_pointer() const -{ - return frame_register_ != 0; -} - -//Number of the nonvolatile register used as the frame pointer, -//using the same encoding for the operation info field of UNWIND_CODE nodes -uint8_t exception_entry::get_frame_pointer_register_number() const -{ - return frame_register_; -} - -//The scaled offset from RSP that is applied to the FP reg when it is established. -//The actual FP reg is set to RSP + 16 * this number, allowing offsets from 0 to 240 -uint8_t exception_entry::get_scaled_rsp_offset() const -{ - return frame_offset_; -} - -//Returns exception directory data (exists on PE+ only) -//Unwind opcodes are not listed, because their format and list are subject to change -const exception_entry_list get_exception_directory_data(const pe_base& pe) -{ - exception_entry_list ret; - - //If image doesn't have exception directory, return empty list - if(!pe.has_exception_directory()) - return ret; - - //Check the length in bytes of the section containing exception directory - if(pe.section_data_length_from_rva(pe.get_directory_rva(image_directory_entry_exception), pe.get_directory_rva(image_directory_entry_exception), section_data_virtual, true) - < sizeof(image_runtime_function_entry)) - throw pe_exception("Incorrect exception directory", pe_exception::incorrect_exception_directory); - - unsigned long current_pos = pe.get_directory_rva(image_directory_entry_exception); - - //Check if structures are DWORD-aligned - if(current_pos % sizeof(uint32_t)) - throw pe_exception("Incorrect exception directory", pe_exception::incorrect_exception_directory); - - //First IMAGE_RUNTIME_FUNCTION_ENTRY table - image_runtime_function_entry exception_table = pe.section_data_from_rva<image_runtime_function_entry>(current_pos, section_data_virtual, true); - - //todo: virtual addresses BeginAddress and EndAddress are not checked to be inside image - while(exception_table.BeginAddress) - { - //Check addresses - if(exception_table.BeginAddress > exception_table.EndAddress) - throw pe_exception("Incorrect exception directory", pe_exception::incorrect_exception_directory); - - //Get unwind information - unwind_info info = pe.section_data_from_rva<unwind_info>(exception_table.UnwindInfoAddress, section_data_virtual, true); - - //Create exception entry and save it - ret.push_back(exception_entry(exception_table, info)); - - //Go to next exception entry - current_pos += sizeof(image_runtime_function_entry); - exception_table = pe.section_data_from_rva<image_runtime_function_entry>(current_pos, section_data_virtual, true); - } - - return ret; -} -} diff --git a/tools/pe_bliss/pe_exception_directory.h b/tools/pe_bliss/pe_exception_directory.h deleted file mode 100644 index 6f4fc2298b..0000000000 --- a/tools/pe_bliss/pe_exception_directory.h +++ /dev/null @@ -1,88 +0,0 @@ -/*************************************************************************/ -/* Copyright (c) 2015 dx, http://kaimi.ru */ -/* */ -/* Permission is hereby granted, free of charge, to any person */ -/* obtaining a copy of this software and associated documentation */ -/* files (the "Software"), to deal in the Software without */ -/* restriction, including without limitation the rights to use, */ -/* copy, modify, merge, publish, distribute, sublicense, and/or */ -/* sell copies of the Software, and to permit persons to whom the */ -/* Software is furnished to do so, subject to the following conditions: */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#pragma once -#include <vector> -#include "pe_structures.h" -#include "pe_base.h" - -namespace pe_bliss -{ -//Class representing exception directory entry -class exception_entry -{ -public: - //Default constructor - exception_entry(); - //Constructor from data - exception_entry(const pe_win::image_runtime_function_entry& entry, const pe_win::unwind_info& unwind_info); - - //Returns starting address of function, affected by exception unwinding - uint32_t get_begin_address() const; - //Returns ending address of function, affected by exception unwinding - uint32_t get_end_address() const; - //Returns unwind info address - uint32_t get_unwind_info_address() const; - - //Returns UNWIND_INFO structure version - uint8_t get_unwind_info_version() const; - - //Returns unwind info flags - uint8_t get_flags() const; - //The function has an exception handler that should be called - //when looking for functions that need to examine exceptions - bool has_exception_handler() const; - //The function has a termination handler that should be called - //when unwinding an exception - bool has_termination_handler() const; - //The unwind info structure is not the primary one for the procedure - bool is_chaininfo() const; - - //Returns size of function prolog - uint8_t get_size_of_prolog() const; - - //Returns number of unwind slots - uint8_t get_number_of_unwind_slots() const; - - //If the function uses frame pointer - bool uses_frame_pointer() const; - //Number of the nonvolatile register used as the frame pointer, - //using the same encoding for the operation info field of UNWIND_CODE nodes - uint8_t get_frame_pointer_register_number() const; - //The scaled offset from RSP that is applied to the FP reg when it is established. - //The actual FP reg is set to RSP + 16 * this number, allowing offsets from 0 to 240 - uint8_t get_scaled_rsp_offset() const; - -private: - uint32_t begin_address_, end_address_, unwind_info_address_; - uint8_t unwind_info_version_; - uint8_t flags_; - uint8_t size_of_prolog_; - uint8_t count_of_codes_; - uint8_t frame_register_, frame_offset_; -}; - -typedef std::vector<exception_entry> exception_entry_list; - -//Returns exception directory data (exists on PE+ only) -//Unwind opcodes are not listed, because their format and list are subject to change -const exception_entry_list get_exception_directory_data(const pe_base& pe); -} diff --git a/tools/pe_bliss/pe_exports.cpp b/tools/pe_bliss/pe_exports.cpp deleted file mode 100644 index c2ad895554..0000000000 --- a/tools/pe_bliss/pe_exports.cpp +++ /dev/null @@ -1,700 +0,0 @@ -/*************************************************************************/ -/* Copyright (c) 2015 dx, http://kaimi.ru */ -/* */ -/* Permission is hereby granted, free of charge, to any person */ -/* obtaining a copy of this software and associated documentation */ -/* files (the "Software"), to deal in the Software without */ -/* restriction, including without limitation the rights to use, */ -/* copy, modify, merge, publish, distribute, sublicense, and/or */ -/* sell copies of the Software, and to permit persons to whom the */ -/* Software is furnished to do so, subject to the following conditions: */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#include <set> -#include <algorithm> -#include <string.h> -#include "pe_exports.h" -#include "utils.h" - -namespace pe_bliss -{ -using namespace pe_win; - -//EXPORTS -//Default constructor -exported_function::exported_function() - :ordinal_(0), rva_(0), has_name_(false), name_ordinal_(0), forward_(false) -{} - -//Returns ordinal of function (actually, ordinal = hint + ordinal base) -uint16_t exported_function::get_ordinal() const -{ - return ordinal_; -} - -//Returns RVA of function -uint32_t exported_function::get_rva() const -{ - return rva_; -} - -//Returns name of function -const std::string& exported_function::get_name() const -{ - return name_; -} - -//Returns true if function has name and name ordinal -bool exported_function::has_name() const -{ - return has_name_; -} - -//Returns name ordinal of function -uint16_t exported_function::get_name_ordinal() const -{ - return name_ordinal_; -} - -//Returns true if function is forwarded to other library -bool exported_function::is_forwarded() const -{ - return forward_; -} - -//Returns the name of forwarded function -const std::string& exported_function::get_forwarded_name() const -{ - return forward_name_; -} - -//Sets ordinal of function -void exported_function::set_ordinal(uint16_t ordinal) -{ - ordinal_ = ordinal; -} - -//Sets RVA of function -void exported_function::set_rva(uint32_t rva) -{ - rva_ = rva; -} - -//Sets name of function (or clears it, if empty name is passed) -void exported_function::set_name(const std::string& name) -{ - name_ = name; - has_name_ = !name.empty(); -} - -//Sets name ordinal -void exported_function::set_name_ordinal(uint16_t name_ordinal) -{ - name_ordinal_ = name_ordinal; -} - -//Sets forwarded function name (or clears it, if empty name is passed) -void exported_function::set_forwarded_name(const std::string& name) -{ - forward_name_ = name; - forward_ = !name.empty(); -} - -//Default constructor -export_info::export_info() - :characteristics_(0), - timestamp_(0), - major_version_(0), - minor_version_(0), - ordinal_base_(0), - number_of_functions_(0), - number_of_names_(0), - address_of_functions_(0), - address_of_names_(0), - address_of_name_ordinals_(0) -{} - -//Returns characteristics -uint32_t export_info::get_characteristics() const -{ - return characteristics_; -} - -//Returns timestamp -uint32_t export_info::get_timestamp() const -{ - return timestamp_; -} - -//Returns major version -uint16_t export_info::get_major_version() const -{ - return major_version_; -} - -//Returns minor version -uint16_t export_info::get_minor_version() const -{ - return minor_version_; -} - -//Returns DLL name -const std::string& export_info::get_name() const -{ - return name_; -} - -//Returns ordinal base -uint32_t export_info::get_ordinal_base() const -{ - return ordinal_base_; -} - -//Returns number of functions -uint32_t export_info::get_number_of_functions() const -{ - return number_of_functions_; -} - -//Returns number of function names -uint32_t export_info::get_number_of_names() const -{ - return number_of_names_; -} - -//Returns RVA of function address table -uint32_t export_info::get_rva_of_functions() const -{ - return address_of_functions_; -} - -//Returns RVA of function name address table -uint32_t export_info::get_rva_of_names() const -{ - return address_of_names_; -} - -//Returns RVA of name ordinals table -uint32_t export_info::get_rva_of_name_ordinals() const -{ - return address_of_name_ordinals_; -} - -//Sets characteristics -void export_info::set_characteristics(uint32_t characteristics) -{ - characteristics_ = characteristics; -} - -//Sets timestamp -void export_info::set_timestamp(uint32_t timestamp) -{ - timestamp_ = timestamp; -} - -//Sets major version -void export_info::set_major_version(uint16_t major_version) -{ - major_version_ = major_version; -} - -//Sets minor version -void export_info::set_minor_version(uint16_t minor_version) -{ - minor_version_ = minor_version; -} - -//Sets DLL name -void export_info::set_name(const std::string& name) -{ - name_ = name; -} - -//Sets ordinal base -void export_info::set_ordinal_base(uint32_t ordinal_base) -{ - ordinal_base_ = ordinal_base; -} - -//Sets number of functions -void export_info::set_number_of_functions(uint32_t number_of_functions) -{ - number_of_functions_ = number_of_functions; -} - -//Sets number of function names -void export_info::set_number_of_names(uint32_t number_of_names) -{ - number_of_names_ = number_of_names; -} - -//Sets RVA of function address table -void export_info::set_rva_of_functions(uint32_t rva_of_functions) -{ - address_of_functions_ = rva_of_functions; -} - -//Sets RVA of function name address table -void export_info::set_rva_of_names(uint32_t rva_of_names) -{ - address_of_names_ = rva_of_names; -} - -//Sets RVA of name ordinals table -void export_info::set_rva_of_name_ordinals(uint32_t rva_of_name_ordinals) -{ - address_of_name_ordinals_ = rva_of_name_ordinals; -} - -const exported_functions_list get_exported_functions(const pe_base& pe, export_info* info); - -//Returns array of exported functions -const exported_functions_list get_exported_functions(const pe_base& pe) -{ - return get_exported_functions(pe, 0); -} - -//Returns array of exported functions and information about export -const exported_functions_list get_exported_functions(const pe_base& pe, export_info& info) -{ - return get_exported_functions(pe, &info); -} - -//Helper: sorts exported function list by ordinals -struct ordinal_sorter -{ -public: - bool operator()(const exported_function& func1, const exported_function& func2) const; -}; - -//Returns array of exported functions and information about export (if info != 0) -const exported_functions_list get_exported_functions(const pe_base& pe, export_info* info) -{ - //Returned exported functions info array - std::vector<exported_function> ret; - - if(pe.has_exports()) - { - //Check the length in bytes of the section containing export directory - if(pe.section_data_length_from_rva(pe.get_directory_rva(image_directory_entry_export), - pe.get_directory_rva(image_directory_entry_export), section_data_virtual, true) - < sizeof(image_export_directory)) - throw pe_exception("Incorrect export directory", pe_exception::incorrect_export_directory); - - image_export_directory exports = pe.section_data_from_rva<image_export_directory>(pe.get_directory_rva(image_directory_entry_export), section_data_virtual, true); - - unsigned long max_name_length; - - if(info) - { - //Save some export info data - info->set_characteristics(exports.Characteristics); - info->set_major_version(exports.MajorVersion); - info->set_minor_version(exports.MinorVersion); - - //Get byte count that we have for dll name - if((max_name_length = pe.section_data_length_from_rva(exports.Name, exports.Name, section_data_virtual, true)) < 2) - throw pe_exception("Incorrect export directory", pe_exception::incorrect_export_directory); - - //Get dll name pointer - const char* dll_name = pe.section_data_from_rva(exports.Name, section_data_virtual, true); - - //Check for null-termination - if(!pe_utils::is_null_terminated(dll_name, max_name_length)) - throw pe_exception("Incorrect export directory", pe_exception::incorrect_export_directory); - - //Save the rest of export information data - info->set_name(dll_name); - info->set_number_of_functions(exports.NumberOfFunctions); - info->set_number_of_names(exports.NumberOfNames); - info->set_ordinal_base(exports.Base); - info->set_rva_of_functions(exports.AddressOfFunctions); - info->set_rva_of_names(exports.AddressOfNames); - info->set_rva_of_name_ordinals(exports.AddressOfNameOrdinals); - info->set_timestamp(exports.TimeDateStamp); - } - - if(!exports.NumberOfFunctions) - return ret; - - //Check IMAGE_EXPORT_DIRECTORY fields - if(exports.NumberOfNames > exports.NumberOfFunctions) - throw pe_exception("Incorrect export directory", pe_exception::incorrect_export_directory); - - //Check some export directory fields - if((!exports.AddressOfNameOrdinals && exports.AddressOfNames) || - (exports.AddressOfNameOrdinals && !exports.AddressOfNames) || - !exports.AddressOfFunctions - || exports.NumberOfFunctions >= pe_utils::max_dword / sizeof(uint32_t) - || exports.NumberOfNames > pe_utils::max_dword / sizeof(uint32_t) - || !pe_utils::is_sum_safe(exports.AddressOfFunctions, exports.NumberOfFunctions * sizeof(uint32_t)) - || !pe_utils::is_sum_safe(exports.AddressOfNames, exports.NumberOfNames * sizeof(uint32_t)) - || !pe_utils::is_sum_safe(exports.AddressOfNameOrdinals, exports.NumberOfFunctions * sizeof(uint32_t)) - || !pe_utils::is_sum_safe(pe.get_directory_rva(image_directory_entry_export), pe.get_directory_size(image_directory_entry_export))) - throw pe_exception("Incorrect export directory", pe_exception::incorrect_export_directory); - - //Check if it is enough bytes to hold AddressOfFunctions table - if(pe.section_data_length_from_rva(exports.AddressOfFunctions, exports.AddressOfFunctions, section_data_virtual, true) - < exports.NumberOfFunctions * sizeof(uint32_t)) - throw pe_exception("Incorrect export directory", pe_exception::incorrect_export_directory); - - if(exports.AddressOfNames) - { - //Check if it is enough bytes to hold name and ordinal tables - if(pe.section_data_length_from_rva(exports.AddressOfNameOrdinals, exports.AddressOfNameOrdinals, section_data_virtual, true) - < exports.NumberOfNames * sizeof(uint16_t)) - throw pe_exception("Incorrect export directory", pe_exception::incorrect_export_directory); - - if(pe.section_data_length_from_rva(exports.AddressOfNames, exports.AddressOfNames, section_data_virtual, true) - < exports.NumberOfNames * sizeof(uint32_t)) - throw pe_exception("Incorrect export directory", pe_exception::incorrect_export_directory); - } - - for(uint32_t ordinal = 0; ordinal < exports.NumberOfFunctions; ordinal++) - { - //Get function address - //Sum and multiplication are safe (checked above) - uint32_t rva = pe.section_data_from_rva<uint32_t>(exports.AddressOfFunctions + ordinal * sizeof(uint32_t), section_data_virtual, true); - - //If we have a skip - if(!rva) - continue; - - exported_function func; - func.set_rva(rva); - - if(!pe_utils::is_sum_safe(exports.Base, ordinal) || exports.Base + ordinal > pe_utils::max_word) - throw pe_exception("Incorrect export directory", pe_exception::incorrect_export_directory); - - func.set_ordinal(static_cast<uint16_t>(ordinal + exports.Base)); - - //Scan for function name ordinal - for(uint32_t i = 0; i < exports.NumberOfNames; i++) - { - uint16_t ordinal2 = pe.section_data_from_rva<uint16_t>(exports.AddressOfNameOrdinals + i * sizeof(uint16_t), section_data_virtual, true); - - //If function has name (and name ordinal) - if(ordinal == ordinal2) - { - //Get function name - //Sum and multiplication are safe (checked above) - uint32_t function_name_rva = pe.section_data_from_rva<uint32_t>(exports.AddressOfNames + i * sizeof(uint32_t), section_data_virtual, true); - - //Get byte count that we have for function name - if((max_name_length = pe.section_data_length_from_rva(function_name_rva, function_name_rva, section_data_virtual, true)) < 2) - throw pe_exception("Incorrect export directory", pe_exception::incorrect_export_directory); - - //Get function name pointer - const char* func_name = pe.section_data_from_rva(function_name_rva, section_data_virtual, true); - - //Check for null-termination - if(!pe_utils::is_null_terminated(func_name, max_name_length)) - throw pe_exception("Incorrect export directory", pe_exception::incorrect_export_directory); - - //Save function info - func.set_name(func_name); - func.set_name_ordinal(ordinal2); - - //If the function is just a redirect, save its name - if(rva >= pe.get_directory_rva(image_directory_entry_export) + sizeof(image_directory_entry_export) && - rva < pe.get_directory_rva(image_directory_entry_export) + pe.get_directory_size(image_directory_entry_export)) - { - if((max_name_length = pe.section_data_length_from_rva(rva, rva, section_data_virtual, true)) < 2) - throw pe_exception("Incorrect export directory", pe_exception::incorrect_export_directory); - - //Get forwarded function name pointer - const char* forwarded_func_name = pe.section_data_from_rva(rva, section_data_virtual, true); - - //Check for null-termination - if(!pe_utils::is_null_terminated(forwarded_func_name, max_name_length)) - throw pe_exception("Incorrect export directory", pe_exception::incorrect_export_directory); - - //Set the name of forwarded function - func.set_forwarded_name(forwarded_func_name); - } - - break; - } - } - - //Add function info to output array - ret.push_back(func); - } - } - - return ret; -} - -//Helper export functions -//Returns pair: <ordinal base for supplied functions; maximum ordinal value for supplied functions> -const std::pair<uint16_t, uint16_t> get_export_ordinal_limits(const exported_functions_list& exports) -{ - if(exports.empty()) - return std::make_pair(0, 0); - - uint16_t max_ordinal = 0; //Maximum ordinal number - uint16_t ordinal_base = pe_utils::max_word; //Minimum ordinal value - for(exported_functions_list::const_iterator it = exports.begin(); it != exports.end(); ++it) - { - const exported_function& func = (*it); - - //Calculate maximum and minimum ordinal numbers - max_ordinal = std::max<uint16_t>(max_ordinal, func.get_ordinal()); - ordinal_base = std::min<uint16_t>(ordinal_base, func.get_ordinal()); - } - - return std::make_pair(ordinal_base, max_ordinal); -} - -//Checks if exported function name already exists -bool exported_name_exists(const std::string& function_name, const exported_functions_list& exports) -{ - for(exported_functions_list::const_iterator it = exports.begin(); it != exports.end(); ++it) - { - if((*it).has_name() && (*it).get_name() == function_name) - return true; - } - - return false; -} - -//Checks if exported function name already exists -bool exported_ordinal_exists(uint16_t ordinal, const exported_functions_list& exports) -{ - for(exported_functions_list::const_iterator it = exports.begin(); it != exports.end(); ++it) - { - if((*it).get_ordinal() == ordinal) - return true; - } - - return false; -} - -//Helper: sorts exported function list by ordinals -bool ordinal_sorter::operator()(const exported_function& func1, const exported_function& func2) const -{ - return func1.get_ordinal() < func2.get_ordinal(); -} - -//Export directory rebuilder -//info - export information -//exported_functions_list - list of exported functions -//exports_section - section where export directory will be placed (must be attached to PE image) -//offset_from_section_start - offset from exports_section raw data start -//save_to_pe_headers - if true, new export directory information will be saved to PE image headers -//auto_strip_last_section - if true and exports are placed in the last section, it will be automatically stripped -//number_of_functions and number_of_names parameters don't matter in "info" when rebuilding, they're calculated independently -//characteristics, major_version, minor_version, timestamp and name are the only used members of "info" structure -//Returns new export directory information -//exported_functions_list is copied intentionally to be sorted by ordinal values later -//Name ordinals in exported function don't matter, they will be recalculated -const image_directory rebuild_exports(pe_base& pe, const export_info& info, exported_functions_list exports, section& exports_section, uint32_t offset_from_section_start, bool save_to_pe_header, bool auto_strip_last_section) -{ - //Check that exports_section is attached to this PE image - if(!pe.section_attached(exports_section)) - throw pe_exception("Exports section must be attached to PE file", pe_exception::section_is_not_attached); - - //Needed space for strings - uint32_t needed_size_for_strings = static_cast<uint32_t>(info.get_name().length() + 1); - uint32_t number_of_names = 0; //Number of named functions - uint32_t max_ordinal = 0; //Maximum ordinal number - uint32_t ordinal_base = static_cast<uint32_t>(-1); //Minimum ordinal value - - if(exports.empty()) - ordinal_base = info.get_ordinal_base(); - - uint32_t needed_size_for_function_names = 0; //Needed space for function name strings - uint32_t needed_size_for_function_forwards = 0; //Needed space for function forwards names - - //List all exported functions - //Calculate needed size for function list - { - //Also check that there're no duplicate names and ordinals - std::set<std::string> used_function_names; - std::set<uint16_t> used_function_ordinals; - - for(exported_functions_list::const_iterator it = exports.begin(); it != exports.end(); ++it) - { - const exported_function& func = (*it); - //Calculate maximum and minimum ordinal numbers - max_ordinal = std::max<uint32_t>(max_ordinal, func.get_ordinal()); - ordinal_base = std::min<uint32_t>(ordinal_base, func.get_ordinal()); - - //Check if ordinal is unique - if(!used_function_ordinals.insert(func.get_ordinal()).second) - throw pe_exception("Duplicate exported function ordinal", pe_exception::duplicate_exported_function_ordinal); - - if(func.has_name()) - { - //If function is named - ++number_of_names; - needed_size_for_function_names += static_cast<uint32_t>(func.get_name().length() + 1); - - //Check if it's name and name ordinal are unique - if(!used_function_names.insert(func.get_name()).second) - throw pe_exception("Duplicate exported function name", pe_exception::duplicate_exported_function_name); - } - - //If function is forwarded to another DLL - if(func.is_forwarded()) - needed_size_for_function_forwards += static_cast<uint32_t>(func.get_forwarded_name().length() + 1); - } - } - - //Sort functions by ordinal value - std::sort(exports.begin(), exports.end(), ordinal_sorter()); - - //Calculate needed space for different things... - needed_size_for_strings += needed_size_for_function_names; - needed_size_for_strings += needed_size_for_function_forwards; - uint32_t needed_size_for_function_name_ordinals = number_of_names * sizeof(uint16_t); - uint32_t needed_size_for_function_name_rvas = number_of_names * sizeof(uint32_t); - uint32_t needed_size_for_function_addresses = (max_ordinal - ordinal_base + 1) * sizeof(uint32_t); - - //Export directory header will be placed first - uint32_t directory_pos = pe_utils::align_up(offset_from_section_start, sizeof(uint32_t)); - - uint32_t needed_size = sizeof(image_export_directory); //Calculate needed size for export tables and strings - //sizeof(IMAGE_EXPORT_DIRECTORY) = export directory header - - //Total needed space... - needed_size += needed_size_for_function_name_ordinals; //For list of names ordinals - needed_size += needed_size_for_function_addresses; //For function RVAs - needed_size += needed_size_for_strings; //For all strings - needed_size += needed_size_for_function_name_rvas; //For function name strings RVAs - - //Check if exports_section is last one. If it's not, check if there's enough place for exports data - if(&exports_section != &*(pe.get_image_sections().end() - 1) && - (exports_section.empty() || pe_utils::align_up(exports_section.get_size_of_raw_data(), pe.get_file_alignment()) < needed_size + directory_pos)) - throw pe_exception("Insufficient space for export directory", pe_exception::insufficient_space); - - std::string& raw_data = exports_section.get_raw_data(); - - //This will be done only if exports_section is the last section of image or for section with unaligned raw length of data - if(raw_data.length() < needed_size + directory_pos) - raw_data.resize(needed_size + directory_pos); //Expand section raw data - - //Library name will be placed after it - uint32_t current_pos_of_function_names = static_cast<uint32_t>(info.get_name().length() + 1 + directory_pos + sizeof(image_export_directory)); - //Next - function names - uint32_t current_pos_of_function_name_ordinals = current_pos_of_function_names + needed_size_for_function_names; - //Next - function name ordinals - uint32_t current_pos_of_function_forwards = current_pos_of_function_name_ordinals + needed_size_for_function_name_ordinals; - //Finally - function addresses - uint32_t current_pos_of_function_addresses = current_pos_of_function_forwards + needed_size_for_function_forwards; - //Next - function names RVAs - uint32_t current_pos_of_function_names_rvas = current_pos_of_function_addresses + needed_size_for_function_addresses; - - { - //Create export directory and fill it - image_export_directory dir = {0}; - dir.Characteristics = info.get_characteristics(); - dir.MajorVersion = info.get_major_version(); - dir.MinorVersion = info.get_minor_version(); - dir.TimeDateStamp = info.get_timestamp(); - dir.NumberOfFunctions = max_ordinal - ordinal_base + 1; - dir.NumberOfNames = number_of_names; - dir.Base = ordinal_base; - dir.AddressOfFunctions = pe.rva_from_section_offset(exports_section, current_pos_of_function_addresses); - dir.AddressOfNameOrdinals = pe.rva_from_section_offset(exports_section, current_pos_of_function_name_ordinals); - dir.AddressOfNames = pe.rva_from_section_offset(exports_section, current_pos_of_function_names_rvas); - dir.Name = pe.rva_from_section_offset(exports_section, directory_pos + sizeof(image_export_directory)); - - //Save it - memcpy(&raw_data[directory_pos], &dir, sizeof(dir)); - } - - //Sve library name - memcpy(&raw_data[directory_pos + sizeof(image_export_directory)], info.get_name().c_str(), info.get_name().length() + 1); - - //A map to sort function names alphabetically - typedef std::map<std::string, uint16_t> funclist; //function name; function name ordinal - funclist funcs; - - uint32_t last_ordinal = ordinal_base; - //Enumerate all exported functions - for(exported_functions_list::const_iterator it = exports.begin(); it != exports.end(); ++it) - { - const exported_function& func = (*it); - - //If we're skipping some ordinals... - if(func.get_ordinal() > last_ordinal) - { - //Fill this function RVAs data with zeros - uint32_t len = sizeof(uint32_t) * (func.get_ordinal() - last_ordinal - 1); - if(len) - { - memset(&raw_data[current_pos_of_function_addresses], 0, len); - current_pos_of_function_addresses += len; - } - - //Save last encountered ordinal - last_ordinal = func.get_ordinal(); - } - - //If function is named, save its name ordinal and name in sorted alphabetically order - if(func.has_name()) - funcs.insert(std::make_pair(func.get_name(), static_cast<uint16_t>(func.get_ordinal() - ordinal_base))); //Calculate name ordinal - - //If function is forwarded to another DLL - if(func.is_forwarded()) - { - //Write its forwarded name and its RVA - uint32_t function_rva = pe.rva_from_section_offset(exports_section, current_pos_of_function_forwards); - memcpy(&raw_data[current_pos_of_function_addresses], &function_rva, sizeof(function_rva)); - current_pos_of_function_addresses += sizeof(function_rva); - - memcpy(&raw_data[current_pos_of_function_forwards], func.get_forwarded_name().c_str(), func.get_forwarded_name().length() + 1); - current_pos_of_function_forwards += static_cast<uint32_t>(func.get_forwarded_name().length() + 1); - } - else - { - //Write actual function RVA - uint32_t function_rva = func.get_rva(); - memcpy(&raw_data[current_pos_of_function_addresses], &function_rva, sizeof(function_rva)); - current_pos_of_function_addresses += sizeof(function_rva); - } - } - - //Enumerate sorted function names - for(funclist::const_iterator it = funcs.begin(); it != funcs.end(); ++it) - { - //Save function name RVA - uint32_t function_name_rva = pe.rva_from_section_offset(exports_section, current_pos_of_function_names); - memcpy(&raw_data[current_pos_of_function_names_rvas], &function_name_rva, sizeof(function_name_rva)); - current_pos_of_function_names_rvas += sizeof(function_name_rva); - - //Save function name - memcpy(&raw_data[current_pos_of_function_names], (*it).first.c_str(), (*it).first.length() + 1); - current_pos_of_function_names += static_cast<uint32_t>((*it).first.length() + 1); - - //Save function name ordinal - uint16_t name_ordinal = (*it).second; - memcpy(&raw_data[current_pos_of_function_name_ordinals], &name_ordinal, sizeof(name_ordinal)); - current_pos_of_function_name_ordinals += sizeof(name_ordinal); - } - - //Adjust section raw and virtual sizes - pe.recalculate_section_sizes(exports_section, auto_strip_last_section); - - image_directory ret(pe.rva_from_section_offset(exports_section, directory_pos), needed_size); - - //If auto-rewrite of PE headers is required - if(save_to_pe_header) - { - pe.set_directory_rva(image_directory_entry_export, ret.get_rva()); - pe.set_directory_size(image_directory_entry_export, ret.get_size()); - } - - return ret; -} -} diff --git a/tools/pe_bliss/pe_exports.h b/tools/pe_bliss/pe_exports.h deleted file mode 100644 index 127cf86ed6..0000000000 --- a/tools/pe_bliss/pe_exports.h +++ /dev/null @@ -1,184 +0,0 @@ -/*************************************************************************/ -/* Copyright (c) 2015 dx, http://kaimi.ru */ -/* */ -/* Permission is hereby granted, free of charge, to any person */ -/* obtaining a copy of this software and associated documentation */ -/* files (the "Software"), to deal in the Software without */ -/* restriction, including without limitation the rights to use, */ -/* copy, modify, merge, publish, distribute, sublicense, and/or */ -/* sell copies of the Software, and to permit persons to whom the */ -/* Software is furnished to do so, subject to the following conditions: */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#pragma once -#include <vector> -#include <string> -#include "pe_structures.h" -#include "pe_base.h" -#include "pe_directory.h" - -namespace pe_bliss -{ -//Class representing exported function -class exported_function -{ -public: - //Default constructor - exported_function(); - - //Returns ordinal of function (actually, ordinal = hint + ordinal base) - uint16_t get_ordinal() const; - - //Returns RVA of function - uint32_t get_rva() const; - - //Returns true if function has name and name ordinal - bool has_name() const; - //Returns name of function - const std::string& get_name() const; - //Returns name ordinal of function - uint16_t get_name_ordinal() const; - - //Returns true if function is forwarded to other library - bool is_forwarded() const; - //Returns the name of forwarded function - const std::string& get_forwarded_name() const; - -public: //Setters do not change everything inside image, they are used by PE class - //You can also use them to rebuild export directory - - //Sets ordinal of function - void set_ordinal(uint16_t ordinal); - - //Sets RVA of function - void set_rva(uint32_t rva); - - //Sets name of function (or clears it, if empty name is passed) - void set_name(const std::string& name); - //Sets name ordinal - void set_name_ordinal(uint16_t name_ordinal); - - //Sets forwarded function name (or clears it, if empty name is passed) - void set_forwarded_name(const std::string& name); - -private: - uint16_t ordinal_; //Function ordinal - uint32_t rva_; //Function RVA - std::string name_; //Function name - bool has_name_; //true == function has name - uint16_t name_ordinal_; //Function name ordinal - bool forward_; //true == function is forwarded - std::string forward_name_; //Name of forwarded function -}; - -//Class representing export information -class export_info -{ -public: - //Default constructor - export_info(); - - //Returns characteristics - uint32_t get_characteristics() const; - //Returns timestamp - uint32_t get_timestamp() const; - //Returns major version - uint16_t get_major_version() const; - //Returns minor version - uint16_t get_minor_version() const; - //Returns DLL name - const std::string& get_name() const; - //Returns ordinal base - uint32_t get_ordinal_base() const; - //Returns number of functions - uint32_t get_number_of_functions() const; - //Returns number of function names - uint32_t get_number_of_names() const; - //Returns RVA of function address table - uint32_t get_rva_of_functions() const; - //Returns RVA of function name address table - uint32_t get_rva_of_names() const; - //Returns RVA of name ordinals table - uint32_t get_rva_of_name_ordinals() const; - -public: //Setters do not change everything inside image, they are used by PE class - //You can also use them to rebuild export directory using rebuild_exports - - //Sets characteristics - void set_characteristics(uint32_t characteristics); - //Sets timestamp - void set_timestamp(uint32_t timestamp); - //Sets major version - void set_major_version(uint16_t major_version); - //Sets minor version - void set_minor_version(uint16_t minor_version); - //Sets DLL name - void set_name(const std::string& name); - //Sets ordinal base - void set_ordinal_base(uint32_t ordinal_base); - //Sets number of functions - void set_number_of_functions(uint32_t number_of_functions); - //Sets number of function names - void set_number_of_names(uint32_t number_of_names); - //Sets RVA of function address table - void set_rva_of_functions(uint32_t rva_of_functions); - //Sets RVA of function name address table - void set_rva_of_names(uint32_t rva_of_names); - //Sets RVA of name ordinals table - void set_rva_of_name_ordinals(uint32_t rva_of_name_ordinals); - -private: - uint32_t characteristics_; - uint32_t timestamp_; - uint16_t major_version_; - uint16_t minor_version_; - std::string name_; - uint32_t ordinal_base_; - uint32_t number_of_functions_; - uint32_t number_of_names_; - uint32_t address_of_functions_; - uint32_t address_of_names_; - uint32_t address_of_name_ordinals_; -}; - -//Exported functions list typedef -typedef std::vector<exported_function> exported_functions_list; - -//Returns array of exported functions -const exported_functions_list get_exported_functions(const pe_base& pe); -//Returns array of exported functions and information about export -const exported_functions_list get_exported_functions(const pe_base& pe, export_info& info); - -//Helper export functions -//Returns pair: <ordinal base for supplied functions; maximum ordinal value for supplied functions> -const std::pair<uint16_t, uint16_t> get_export_ordinal_limits(const exported_functions_list& exports); - -//Checks if exported function name already exists -bool exported_name_exists(const std::string& function_name, const exported_functions_list& exports); - -//Checks if exported function ordinal already exists -bool exported_ordinal_exists(uint16_t ordinal, const exported_functions_list& exports); - -//Export directory rebuilder -//info - export information -//exported_functions_list - list of exported functions -//exports_section - section where export directory will be placed (must be attached to PE image) -//offset_from_section_start - offset from exports_section raw data start -//save_to_pe_headers - if true, new export directory information will be saved to PE image headers -//auto_strip_last_section - if true and exports are placed in the last section, it will be automatically stripped -//number_of_functions and number_of_names parameters don't matter in "info" when rebuilding, they're calculated independently -//characteristics, major_version, minor_version, timestamp and name are the only used members of "info" structure -//Returns new export directory information -//exported_functions_list is copied intentionally to be sorted by ordinal values later -//Name ordinals in exported function don't matter, they will be recalculated -const image_directory rebuild_exports(pe_base& pe, const export_info& info, exported_functions_list exports, section& exports_section, uint32_t offset_from_section_start = 0, bool save_to_pe_header = true, bool auto_strip_last_section = true); -} diff --git a/tools/pe_bliss/pe_factory.cpp b/tools/pe_bliss/pe_factory.cpp deleted file mode 100644 index f6d8a3e1ed..0000000000 --- a/tools/pe_bliss/pe_factory.cpp +++ /dev/null @@ -1,43 +0,0 @@ -/*************************************************************************/ -/* Copyright (c) 2015 dx, http://kaimi.ru */ -/* */ -/* Permission is hereby granted, free of charge, to any person */ -/* obtaining a copy of this software and associated documentation */ -/* files (the "Software"), to deal in the Software without */ -/* restriction, including without limitation the rights to use, */ -/* copy, modify, merge, publish, distribute, sublicense, and/or */ -/* sell copies of the Software, and to permit persons to whom the */ -/* Software is furnished to do so, subject to the following conditions: */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#include "pe_factory.h" -#include "pe_properties_generic.h" - -namespace pe_bliss -{ -pe_base pe_factory::create_pe(std::istream& file, bool read_debug_raw_data) -{ - return pe_base::get_pe_type(file) == pe_type_32 - ? pe_base(file, pe_properties_32(), read_debug_raw_data) - : pe_base(file, pe_properties_64(), read_debug_raw_data); -} - -pe_base pe_factory::create_pe(const char* file_path, bool read_debug_raw_data) -{ - std::ifstream pe_file(file_path, std::ios::in | std::ios::binary); - if(!pe_file) - { - throw pe_exception("Error in open file.", pe_exception::stream_is_bad); - } - return pe_factory::create_pe(pe_file,read_debug_raw_data); -} -} diff --git a/tools/pe_bliss/pe_factory.h b/tools/pe_bliss/pe_factory.h deleted file mode 100644 index 60b42d9b71..0000000000 --- a/tools/pe_bliss/pe_factory.h +++ /dev/null @@ -1,39 +0,0 @@ -/*************************************************************************/ -/* Copyright (c) 2015 dx, http://kaimi.ru */ -/* */ -/* Permission is hereby granted, free of charge, to any person */ -/* obtaining a copy of this software and associated documentation */ -/* files (the "Software"), to deal in the Software without */ -/* restriction, including without limitation the rights to use, */ -/* copy, modify, merge, publish, distribute, sublicense, and/or */ -/* sell copies of the Software, and to permit persons to whom the */ -/* Software is furnished to do so, subject to the following conditions: */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#pragma once -#include <memory> -#include <istream> -#include <fstream> -#include "pe_base.h" - -namespace pe_bliss -{ -class pe_factory -{ -public: - //Creates pe_base class instance from PE or PE+ istream - //If read_bound_import_raw_data, raw bound import data will be read (used to get bound import info) - //If read_debug_raw_data, raw debug data will be read (used to get image debug info) - static pe_base create_pe(std::istream& file, bool read_debug_raw_data = true); - static pe_base create_pe(const char* file_path, bool read_debug_raw_data = true); -}; -} diff --git a/tools/pe_bliss/pe_imports.cpp b/tools/pe_bliss/pe_imports.cpp deleted file mode 100644 index 0a6c01d6c0..0000000000 --- a/tools/pe_bliss/pe_imports.cpp +++ /dev/null @@ -1,777 +0,0 @@ -/*************************************************************************/ -/* Copyright (c) 2015 dx, http://kaimi.ru */ -/* */ -/* Permission is hereby granted, free of charge, to any person */ -/* obtaining a copy of this software and associated documentation */ -/* files (the "Software"), to deal in the Software without */ -/* restriction, including without limitation the rights to use, */ -/* copy, modify, merge, publish, distribute, sublicense, and/or */ -/* sell copies of the Software, and to permit persons to whom the */ -/* Software is furnished to do so, subject to the following conditions: */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#include <string.h> -#include "pe_imports.h" -#include "pe_properties_generic.h" - -namespace pe_bliss -{ -using namespace pe_win; - -//IMPORTS -//Default constructor -//If set_to_pe_headers = true, IMAGE_DIRECTORY_ENTRY_IMPORT entry will be reset -//to new value after import rebuilding -//If auto_zero_directory_entry_iat = true, IMAGE_DIRECTORY_ENTRY_IAT will be set to zero -//IMAGE_DIRECTORY_ENTRY_IAT is used by loader to temporarily make section, where IMAGE_DIRECTORY_ENTRY_IAT RVA points, writeable -//to be able to modify IAT thunks -import_rebuilder_settings::import_rebuilder_settings(bool set_to_pe_headers, bool auto_zero_directory_entry_iat) - :offset_from_section_start_(0), - build_original_iat_(true), - save_iat_and_original_iat_rvas_(true), - fill_missing_original_iats_(false), - set_to_pe_headers_(set_to_pe_headers), - zero_directory_entry_iat_(auto_zero_directory_entry_iat), - rewrite_iat_and_original_iat_contents_(false), - auto_strip_last_section_(true) -{} - -//Returns offset from section start where import directory data will be placed -uint32_t import_rebuilder_settings::get_offset_from_section_start() const -{ - return offset_from_section_start_; -} - -//Returns true if Original import address table (IAT) will be rebuilt -bool import_rebuilder_settings::build_original_iat() const -{ - return build_original_iat_; -} - -//Returns true if Original import address and import address tables will not be rebuilt, -//works only if import descriptor IAT (and orig.IAT, if present) RVAs are not zero -bool import_rebuilder_settings::save_iat_and_original_iat_rvas() const -{ - return save_iat_and_original_iat_rvas_; -} - -//Returns true if Original import address and import address tables contents will be rewritten -//works only if import descriptor IAT (and orig.IAT, if present) RVAs are not zero -//and save_iat_and_original_iat_rvas is true -bool import_rebuilder_settings::rewrite_iat_and_original_iat_contents() const -{ - return rewrite_iat_and_original_iat_contents_; -} - -//Returns true if original missing IATs will be rebuilt -//(only if IATs are saved) -bool import_rebuilder_settings::fill_missing_original_iats() const -{ - return fill_missing_original_iats_; -} - -//Returns true if PE headers should be updated automatically after rebuilding of imports -bool import_rebuilder_settings::auto_set_to_pe_headers() const -{ - return set_to_pe_headers_; -} - -//Returns true if IMAGE_DIRECTORY_ENTRY_IAT must be zeroed, works only if auto_set_to_pe_headers = true -bool import_rebuilder_settings::zero_directory_entry_iat() const -{ - return zero_directory_entry_iat_; -} - -//Returns true if the last section should be stripped automatically, if imports are inside it -bool import_rebuilder_settings::auto_strip_last_section_enabled() const -{ - return auto_strip_last_section_; -} - -//Sets offset from section start where import directory data will be placed -void import_rebuilder_settings::set_offset_from_section_start(uint32_t offset) -{ - offset_from_section_start_ = offset; -} - -//Sets if Original import address table (IAT) will be rebuilt -void import_rebuilder_settings::build_original_iat(bool enable) -{ - build_original_iat_ = enable; -} - -//Sets if Original import address and import address tables will not be rebuilt, -//works only if import descriptor IAT (and orig.IAT, if present) RVAs are not zero -void import_rebuilder_settings::save_iat_and_original_iat_rvas(bool enable, bool enable_rewrite_iat_and_original_iat_contents) -{ - save_iat_and_original_iat_rvas_ = enable; - if(save_iat_and_original_iat_rvas_) - rewrite_iat_and_original_iat_contents_ = enable_rewrite_iat_and_original_iat_contents; - else - rewrite_iat_and_original_iat_contents_ = false; -} - -//Sets if original missing IATs will be rebuilt -//(only if IATs are saved) -void import_rebuilder_settings::fill_missing_original_iats(bool enable) -{ - fill_missing_original_iats_ = enable; -} - -//Sets if PE headers should be updated automatically after rebuilding of imports -void import_rebuilder_settings::auto_set_to_pe_headers(bool enable) -{ - set_to_pe_headers_ = enable; -} - -//Sets if IMAGE_DIRECTORY_ENTRY_IAT must be zeroed, works only if auto_set_to_pe_headers = true -void import_rebuilder_settings::zero_directory_entry_iat(bool enable) -{ - zero_directory_entry_iat_ = enable; -} - -//Sets if the last section should be stripped automatically, if imports are inside it, default true -void import_rebuilder_settings::enable_auto_strip_last_section(bool enable) -{ - auto_strip_last_section_ = enable; -} - -//Default constructor -imported_function::imported_function() - :hint_(0), ordinal_(0), iat_va_(0) -{} - -//Returns name of function -const std::string& imported_function::get_name() const -{ - return name_; -} - -//Returns true if imported function has name (and hint) -bool imported_function::has_name() const -{ - return !name_.empty(); -} - -//Returns hint -uint16_t imported_function::get_hint() const -{ - return hint_; -} - -//Returns ordinal of function -uint16_t imported_function::get_ordinal() const -{ - return ordinal_; -} - -//Returns IAT entry VA (usable if image has both IAT and original IAT and is bound) -uint64_t imported_function::get_iat_va() const -{ - return iat_va_; -} - -//Sets name of function -void imported_function::set_name(const std::string& name) -{ - name_ = name; -} - -//Sets hint -void imported_function::set_hint(uint16_t hint) -{ - hint_ = hint; -} - -//Sets ordinal -void imported_function::set_ordinal(uint16_t ordinal) -{ - ordinal_ = ordinal; -} - -//Sets IAT entry VA (usable if image has both IAT and original IAT and is bound) -void imported_function::set_iat_va(uint64_t va) -{ - iat_va_ = va; -} - -//Default constructor -import_library::import_library() - :rva_to_iat_(0), rva_to_original_iat_(0), timestamp_(0) -{} - -//Returns name of library -const std::string& import_library::get_name() const -{ - return name_; -} - -//Returns RVA to Import Address Table (IAT) -uint32_t import_library::get_rva_to_iat() const -{ - return rva_to_iat_; -} - -//Returns RVA to Original Import Address Table (Original IAT) -uint32_t import_library::get_rva_to_original_iat() const -{ - return rva_to_original_iat_; -} - -//Returns timestamp -uint32_t import_library::get_timestamp() const -{ - return timestamp_; -} - -//Sets name of library -void import_library::set_name(const std::string& name) -{ - name_ = name; -} - -//Sets RVA to Import Address Table (IAT) -void import_library::set_rva_to_iat(uint32_t rva_to_iat) -{ - rva_to_iat_ = rva_to_iat; -} - -//Sets RVA to Original Import Address Table (Original IAT) -void import_library::set_rva_to_original_iat(uint32_t rva_to_original_iat) -{ - rva_to_original_iat_ = rva_to_original_iat; -} - -//Sets timestamp -void import_library::set_timestamp(uint32_t timestamp) -{ - timestamp_ = timestamp; -} - -//Returns imported functions list -const import_library::imported_list& import_library::get_imported_functions() const -{ - return imports_; -} - -//Adds imported function -void import_library::add_import(const imported_function& func) -{ - imports_.push_back(func); -} - -//Clears imported functions list -void import_library::clear_imports() -{ - imports_.clear(); -} - -const imported_functions_list get_imported_functions(const pe_base& pe) -{ - return (pe.get_pe_type() == pe_type_32 ? - get_imported_functions_base<pe_types_class_32>(pe) - : get_imported_functions_base<pe_types_class_64>(pe)); -} - -const image_directory rebuild_imports(pe_base& pe, const imported_functions_list& imports, section& import_section, const import_rebuilder_settings& import_settings) -{ - return (pe.get_pe_type() == pe_type_32 ? - rebuild_imports_base<pe_types_class_32>(pe, imports, import_section, import_settings) - : rebuild_imports_base<pe_types_class_64>(pe, imports, import_section, import_settings)); -} - -//Returns imported functions list with related libraries info -template<typename PEClassType> -const imported_functions_list get_imported_functions_base(const pe_base& pe) -{ - imported_functions_list ret; - - //If image has no imports, return empty array - if(!pe.has_imports()) - return ret; - - unsigned long current_descriptor_pos = pe.get_directory_rva(image_directory_entry_import); - //Get first IMAGE_IMPORT_DESCRIPTOR - image_import_descriptor import_descriptor = pe.section_data_from_rva<image_import_descriptor>(current_descriptor_pos, section_data_virtual, true); - - //Iterate them until we reach zero-element - //We don't need to check correctness of this, because exception will be thrown - //inside of loop if we go outsize of section - while(import_descriptor.Name) - { - //Get imported library information - import_library lib; - - unsigned long max_name_length; - //Get byte count that we have for library name - if((max_name_length = pe.section_data_length_from_rva(import_descriptor.Name, import_descriptor.Name, section_data_virtual, true)) < 2) - throw pe_exception("Incorrect import directory", pe_exception::incorrect_import_directory); - - //Get DLL name pointer - const char* dll_name = pe.section_data_from_rva(import_descriptor.Name, section_data_virtual, true); - - //Check for null-termination - if(!pe_utils::is_null_terminated(dll_name, max_name_length)) - throw pe_exception("Incorrect import directory", pe_exception::incorrect_import_directory); - - //Set library name - lib.set_name(dll_name); - //Set library timestamp - lib.set_timestamp(import_descriptor.TimeDateStamp); - //Set library RVA to IAT and original IAT - lib.set_rva_to_iat(import_descriptor.FirstThunk); - lib.set_rva_to_original_iat(import_descriptor.OriginalFirstThunk); - - //Get RVA to IAT (it must be filled by loader when loading PE) - uint32_t current_thunk_rva = import_descriptor.FirstThunk; - typename PEClassType::BaseSize import_address_table = pe.section_data_from_rva<typename PEClassType::BaseSize>(current_thunk_rva, section_data_virtual, true); - - //Get RVA to original IAT (lookup table), which must handle imported functions names - //Some linkers leave this pointer zero-filled - //Such image is valid, but it is not possible to restore imported functions names - //afted image was loaded, because IAT becomes the only one table - //containing both function names and function RVAs after loading - uint32_t current_original_thunk_rva = import_descriptor.OriginalFirstThunk; - typename PEClassType::BaseSize import_lookup_table = current_original_thunk_rva == 0 ? import_address_table : pe.section_data_from_rva<typename PEClassType::BaseSize>(current_original_thunk_rva, section_data_virtual, true); - if(current_original_thunk_rva == 0) - current_original_thunk_rva = current_thunk_rva; - - //List all imported functions for current DLL - if(import_lookup_table != 0 && import_address_table != 0) - { - while(true) - { - //Imported function description - imported_function func; - - //Get VA from IAT - typename PEClassType::BaseSize address = pe.section_data_from_rva<typename PEClassType::BaseSize>(current_thunk_rva, section_data_virtual, true); - //Move pointer - current_thunk_rva += sizeof(typename PEClassType::BaseSize); - - //Jump to next DLL if we finished with this one - if(!address) - break; - - func.set_iat_va(address); - - //Get VA from original IAT - typename PEClassType::BaseSize lookup = pe.section_data_from_rva<typename PEClassType::BaseSize>(current_original_thunk_rva, section_data_virtual, true); - //Move pointer - current_original_thunk_rva += sizeof(typename PEClassType::BaseSize); - - //Check if function is imported by ordinal - if((lookup & PEClassType::ImportSnapFlag) != 0) - { - //Set function ordinal - func.set_ordinal(static_cast<uint16_t>(lookup & 0xffff)); - } - else - { - //Get byte count that we have for function name - if(lookup > static_cast<uint32_t>(-1) - sizeof(uint16_t)) - throw pe_exception("Incorrect import directory", pe_exception::incorrect_import_directory); - - //Get maximum available length of function name - if((max_name_length = pe.section_data_length_from_rva(static_cast<uint32_t>(lookup + sizeof(uint16_t)), static_cast<uint32_t>(lookup + sizeof(uint16_t)), section_data_virtual, true)) < 2) - throw pe_exception("Incorrect import directory", pe_exception::incorrect_import_directory); - - //Get imported function name - const char* func_name = pe.section_data_from_rva(static_cast<uint32_t>(lookup + sizeof(uint16_t)), section_data_virtual, true); - - //Check for null-termination - if(!pe_utils::is_null_terminated(func_name, max_name_length)) - throw pe_exception("Incorrect import directory", pe_exception::incorrect_import_directory); - - //HINT in import table is ORDINAL in export table - uint16_t hint = pe.section_data_from_rva<uint16_t>(static_cast<uint32_t>(lookup), section_data_virtual, true); - - //Save hint and name - func.set_name(func_name); - func.set_hint(hint); - } - - //Add function to list - lib.add_import(func); - } - } - - //Check possible overflow - if(!pe_utils::is_sum_safe(current_descriptor_pos, sizeof(image_import_descriptor))) - throw pe_exception("Incorrect import directory", pe_exception::incorrect_import_directory); - - //Go to next library - current_descriptor_pos += sizeof(image_import_descriptor); - import_descriptor = pe.section_data_from_rva<image_import_descriptor>(current_descriptor_pos, section_data_virtual, true); - - //Save import information - ret.push_back(lib); - } - - //Return resulting list - return ret; -} - - -//Simple import directory rebuilder -//You can get all image imports with get_imported_functions() function -//You can use returned value to, for example, add new imported library with some functions -//to the end of list of imported libraries -//To keep PE file working, rebuild its imports with save_iat_and_original_iat_rvas = true (default) -//Don't add new imported functions to existing imported library entries, because this can cause -//rewriting of some used memory (or other IAT/orig.IAT fields) by system loader -//The safest way is just adding import libraries with functions to the end of imported_functions_list array -template<typename PEClassType> -const image_directory rebuild_imports_base(pe_base& pe, const imported_functions_list& imports, section& import_section, const import_rebuilder_settings& import_settings) -{ - //Check that import_section is attached to this PE image - if(!pe.section_attached(import_section)) - throw pe_exception("Import section must be attached to PE file", pe_exception::section_is_not_attached); - - uint32_t needed_size = 0; //Calculate needed size for import structures and strings - uint32_t needed_size_for_strings = 0; //Calculate needed size for import strings (library and function names and hints) - uint32_t size_of_iat = 0; //Size of IAT structures - - needed_size += static_cast<uint32_t>((1 /* ending null descriptor */ + imports.size()) * sizeof(image_import_descriptor)); - - //Enumerate imported functions - for(imported_functions_list::const_iterator it = imports.begin(); it != imports.end(); ++it) - { - needed_size_for_strings += static_cast<uint32_t>((*it).get_name().length() + 1 /* nullbyte */); - - const import_library::imported_list& funcs = (*it).get_imported_functions(); - - //IMAGE_THUNK_DATA - size_of_iat += static_cast<uint32_t>(sizeof(typename PEClassType::BaseSize) * (1 /*ending null */ + funcs.size())); - - //Enumerate all imported functions in library - for(import_library::imported_list::const_iterator f = funcs.begin(); f != funcs.end(); ++f) - { - if((*f).has_name()) - needed_size_for_strings += static_cast<uint32_t>((*f).get_name().length() + 1 /* nullbyte */ + sizeof(uint16_t) /* hint */); - } - } - - if(import_settings.build_original_iat() || import_settings.fill_missing_original_iats()) - needed_size += size_of_iat * 2; //We'll have two similar-sized IATs if we're building original IAT - else - needed_size += size_of_iat; - - needed_size += sizeof(typename PEClassType::BaseSize); //Maximum align for IAT and original IAT - - //Total needed size for import structures and strings - needed_size += needed_size_for_strings; - - //Check if import_section is last one. If it's not, check if there's enough place for import data - if(&import_section != &*(pe.get_image_sections().end() - 1) && - (import_section.empty() || pe_utils::align_up(import_section.get_size_of_raw_data(), pe.get_file_alignment()) < needed_size + import_settings.get_offset_from_section_start())) - throw pe_exception("Insufficient space for import directory", pe_exception::insufficient_space); - - std::string& raw_data = import_section.get_raw_data(); - - //This will be done only if image_section is the last section of image or for section with unaligned raw length of data - if(raw_data.length() < needed_size + import_settings.get_offset_from_section_start()) - raw_data.resize(needed_size + import_settings.get_offset_from_section_start()); //Expand section raw data - - uint32_t current_string_pointer = import_settings.get_offset_from_section_start();/* we will paste structures after strings */ - - //Position for IAT - uint32_t current_pos_for_iat = pe_utils::align_up(static_cast<uint32_t>(needed_size_for_strings + import_settings.get_offset_from_section_start() + (1 + imports.size()) * sizeof(image_import_descriptor)), sizeof(typename PEClassType::BaseSize)); - //Position for original IAT - uint32_t current_pos_for_original_iat = current_pos_for_iat + size_of_iat; - //Position for import descriptors - uint32_t current_pos_for_descriptors = needed_size_for_strings + import_settings.get_offset_from_section_start(); - - //Build imports - for(imported_functions_list::const_iterator it = imports.begin(); it != imports.end(); ++it) - { - //Create import descriptor - image_import_descriptor descr; - memset(&descr, 0, sizeof(descr)); - descr.TimeDateStamp = (*it).get_timestamp(); //Restore timestamp - descr.Name = pe.rva_from_section_offset(import_section, current_string_pointer); //Library name RVA - - //If we should save IAT for current import descriptor - bool save_iats_for_this_descriptor = import_settings.save_iat_and_original_iat_rvas() && (*it).get_rva_to_iat() != 0; - //If we should write original IAT - bool write_original_iat = (!save_iats_for_this_descriptor && import_settings.build_original_iat()) || import_settings.fill_missing_original_iats(); - - //If we should rewrite saved original IAT for current import descriptor (without changing its position) - bool rewrite_saved_original_iat = save_iats_for_this_descriptor && import_settings.rewrite_iat_and_original_iat_contents() && import_settings.build_original_iat(); - //If we should rewrite saved IAT for current import descriptor (without changing its position) - bool rewrite_saved_iat = save_iats_for_this_descriptor && import_settings.rewrite_iat_and_original_iat_contents() && (*it).get_rva_to_iat() != 0; - - //Helper values if we're rewriting existing IAT or orig.IAT - uint32_t original_first_thunk = 0; - uint32_t first_thunk = 0; - - if(save_iats_for_this_descriptor) - { - //If there's no original IAT and we're asked to rebuild missing original IATs - if(!(*it).get_rva_to_original_iat() && import_settings.fill_missing_original_iats()) - descr.OriginalFirstThunk = import_settings.build_original_iat() ? pe.rva_from_section_offset(import_section, current_pos_for_original_iat) : 0; - else - descr.OriginalFirstThunk = import_settings.build_original_iat() ? (*it).get_rva_to_original_iat() : 0; - - descr.FirstThunk = (*it).get_rva_to_iat(); - - original_first_thunk = descr.OriginalFirstThunk; - first_thunk = descr.FirstThunk; - - if(rewrite_saved_original_iat) - { - if((*it).get_rva_to_original_iat()) - write_original_iat = true; - else - rewrite_saved_original_iat = false; - } - - if(rewrite_saved_iat) - save_iats_for_this_descriptor = false; - } - else - { - //We are creating new IAT and original IAT (if needed) - descr.OriginalFirstThunk = import_settings.build_original_iat() ? pe.rva_from_section_offset(import_section, current_pos_for_original_iat) : 0; - descr.FirstThunk = pe.rva_from_section_offset(import_section, current_pos_for_iat); - } - - //Save import descriptor - memcpy(&raw_data[current_pos_for_descriptors], &descr, sizeof(descr)); - current_pos_for_descriptors += sizeof(descr); - - //Save library name - memcpy(&raw_data[current_string_pointer], (*it).get_name().c_str(), (*it).get_name().length() + 1 /* nullbyte */); - current_string_pointer += static_cast<uint32_t>((*it).get_name().length() + 1 /* nullbyte */); - - //List all imported functions - const import_library::imported_list& funcs = (*it).get_imported_functions(); - for(import_library::imported_list::const_iterator f = funcs.begin(); f != funcs.end(); ++f) - { - if((*f).has_name()) //If function is imported by name - { - //Get RVA of IMAGE_IMPORT_BY_NAME - typename PEClassType::BaseSize rva_of_named_import = pe.rva_from_section_offset(import_section, current_string_pointer); - - if(!save_iats_for_this_descriptor) - { - if(write_original_iat) - { - //We're creating original IATs - so we can write to IAT saved VA (because IMAGE_IMPORT_BY_NAME will be read - //by PE loader from original IAT) - typename PEClassType::BaseSize iat_value = static_cast<typename PEClassType::BaseSize>((*f).get_iat_va()); - - if(rewrite_saved_iat) - { - if(pe.section_data_length_from_rva(first_thunk, first_thunk, section_data_raw, true) <= sizeof(iat_value)) - throw pe_exception("Insufficient space inside initial IAT", pe_exception::insufficient_space); - - memcpy(pe.section_data_from_rva(first_thunk, true), &iat_value, sizeof(iat_value)); - - first_thunk += sizeof(iat_value); - } - else - { - memcpy(&raw_data[current_pos_for_iat], &iat_value, sizeof(iat_value)); - current_pos_for_iat += sizeof(rva_of_named_import); - } - } - else - { - //Else - write to IAT RVA of IMAGE_IMPORT_BY_NAME - if(rewrite_saved_iat) - { - if(pe.section_data_length_from_rva(first_thunk, first_thunk, section_data_raw, true) <= sizeof(rva_of_named_import)) - throw pe_exception("Insufficient space inside initial IAT", pe_exception::insufficient_space); - - memcpy(pe.section_data_from_rva(first_thunk, true), &rva_of_named_import, sizeof(rva_of_named_import)); - - first_thunk += sizeof(rva_of_named_import); - } - else - { - memcpy(&raw_data[current_pos_for_iat], &rva_of_named_import, sizeof(rva_of_named_import)); - current_pos_for_iat += sizeof(rva_of_named_import); - } - } - } - - if(write_original_iat) - { - if(rewrite_saved_original_iat) - { - if(pe.section_data_length_from_rva(original_first_thunk, original_first_thunk, section_data_raw, true) <= sizeof(rva_of_named_import)) - throw pe_exception("Insufficient space inside initial original IAT", pe_exception::insufficient_space); - - memcpy(pe.section_data_from_rva(original_first_thunk, true), &rva_of_named_import, sizeof(rva_of_named_import)); - - original_first_thunk += sizeof(rva_of_named_import); - } - else - { - //We're creating original IATs - memcpy(&raw_data[current_pos_for_original_iat], &rva_of_named_import, sizeof(rva_of_named_import)); - current_pos_for_original_iat += sizeof(rva_of_named_import); - } - } - - //Write IMAGE_IMPORT_BY_NAME (WORD hint + string function name) - uint16_t hint = (*f).get_hint(); - memcpy(&raw_data[current_string_pointer], &hint, sizeof(hint)); - memcpy(&raw_data[current_string_pointer + sizeof(uint16_t)], (*f).get_name().c_str(), (*f).get_name().length() + 1 /* nullbyte */); - current_string_pointer += static_cast<uint32_t>((*f).get_name().length() + 1 /* nullbyte */ + sizeof(uint16_t) /* hint */); - } - else //Function is imported by ordinal - { - uint16_t ordinal = (*f).get_ordinal(); - typename PEClassType::BaseSize thunk_value = ordinal; - thunk_value |= PEClassType::ImportSnapFlag; //Imported by ordinal - - if(!save_iats_for_this_descriptor) - { - if(write_original_iat) - { - //We're creating original IATs - so we can wtire to IAT saved VA (because ordinal will be read - //by PE loader from original IAT) - typename PEClassType::BaseSize iat_value = static_cast<typename PEClassType::BaseSize>((*f).get_iat_va()); - if(rewrite_saved_iat) - { - if(pe.section_data_length_from_rva(first_thunk, first_thunk, section_data_raw, true) <= sizeof(iat_value)) - throw pe_exception("Insufficient space inside initial IAT", pe_exception::insufficient_space); - - memcpy(pe.section_data_from_rva(first_thunk, true), &iat_value, sizeof(iat_value)); - - first_thunk += sizeof(iat_value); - } - else - { - memcpy(&raw_data[current_pos_for_iat], &iat_value, sizeof(iat_value)); - current_pos_for_iat += sizeof(thunk_value); - } - } - else - { - //Else - write ordinal to IAT - if(rewrite_saved_iat) - { - if(pe.section_data_length_from_rva(first_thunk, first_thunk, section_data_raw, true) <= sizeof(thunk_value)) - throw pe_exception("Insufficient space inside initial IAT", pe_exception::insufficient_space); - - memcpy(pe.section_data_from_rva(first_thunk, true), &thunk_value, sizeof(thunk_value)); - - first_thunk += sizeof(thunk_value); - } - else - { - memcpy(&raw_data[current_pos_for_iat], &thunk_value, sizeof(thunk_value)); - } - } - } - - //We're writing ordinal to original IAT slot - if(write_original_iat) - { - if(rewrite_saved_original_iat) - { - if(pe.section_data_length_from_rva(original_first_thunk, original_first_thunk, section_data_raw, true) <= sizeof(thunk_value)) - throw pe_exception("Insufficient space inside initial original IAT", pe_exception::insufficient_space); - - memcpy(pe.section_data_from_rva(original_first_thunk, true), &thunk_value, sizeof(thunk_value)); - - original_first_thunk += sizeof(thunk_value); - } - else - { - memcpy(&raw_data[current_pos_for_original_iat], &thunk_value, sizeof(thunk_value)); - current_pos_for_original_iat += sizeof(thunk_value); - } - } - } - } - - if(!save_iats_for_this_descriptor) - { - //Ending null thunks - typename PEClassType::BaseSize thunk_value = 0; - - if(rewrite_saved_iat) - { - if(pe.section_data_length_from_rva(first_thunk, first_thunk, section_data_raw, true) <= sizeof(thunk_value)) - throw pe_exception("Insufficient space inside initial IAT", pe_exception::insufficient_space); - - memcpy(pe.section_data_from_rva(first_thunk, true), &thunk_value, sizeof(thunk_value)); - - first_thunk += sizeof(thunk_value); - } - else - { - memcpy(&raw_data[current_pos_for_iat], &thunk_value, sizeof(thunk_value)); - current_pos_for_iat += sizeof(thunk_value); - } - } - - if(write_original_iat) - { - //Ending null thunks - typename PEClassType::BaseSize thunk_value = 0; - - if(rewrite_saved_original_iat) - { - if(pe.section_data_length_from_rva(original_first_thunk, original_first_thunk, section_data_raw, true) <= sizeof(thunk_value)) - throw pe_exception("Insufficient space inside initial original IAT", pe_exception::insufficient_space); - - memcpy(pe.section_data_from_rva(original_first_thunk, true), &thunk_value, sizeof(thunk_value)); - - original_first_thunk += sizeof(thunk_value); - } - else - { - memcpy(&raw_data[current_pos_for_original_iat], &thunk_value, sizeof(thunk_value)); - current_pos_for_original_iat += sizeof(thunk_value); - } - } - } - - { - //Null ending descriptor - image_import_descriptor descr; - memset(&descr, 0, sizeof(descr)); - memcpy(&raw_data[current_pos_for_descriptors], &descr, sizeof(descr)); - } - - //Strip data a little, if we saved some place - //We're allocating more space than needed, if present original IAT and IAT are saved - raw_data.resize(current_pos_for_original_iat); - - //Adjust section raw and virtual sizes - pe.recalculate_section_sizes(import_section, import_settings.auto_strip_last_section_enabled()); - - //Return information about rebuilt import directory - image_directory ret(pe.rva_from_section_offset(import_section, import_settings.get_offset_from_section_start() + needed_size_for_strings), needed_size - needed_size_for_strings); - - //If auto-rewrite of PE headers is required - if(import_settings.auto_set_to_pe_headers()) - { - pe.set_directory_rva(image_directory_entry_import, ret.get_rva()); - pe.set_directory_size(image_directory_entry_import, ret.get_size()); - - //If we are requested to zero IMAGE_DIRECTORY_ENTRY_IAT also - if(import_settings.zero_directory_entry_iat()) - { - pe.set_directory_rva(image_directory_entry_iat, 0); - pe.set_directory_size(image_directory_entry_iat, 0); - } - } - - return ret; -} -} diff --git a/tools/pe_bliss/pe_imports.h b/tools/pe_bliss/pe_imports.h deleted file mode 100644 index 681b5b59bd..0000000000 --- a/tools/pe_bliss/pe_imports.h +++ /dev/null @@ -1,208 +0,0 @@ -/*************************************************************************/ -/* Copyright (c) 2015 dx, http://kaimi.ru */ -/* */ -/* Permission is hereby granted, free of charge, to any person */ -/* obtaining a copy of this software and associated documentation */ -/* files (the "Software"), to deal in the Software without */ -/* restriction, including without limitation the rights to use, */ -/* copy, modify, merge, publish, distribute, sublicense, and/or */ -/* sell copies of the Software, and to permit persons to whom the */ -/* Software is furnished to do so, subject to the following conditions: */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#pragma once -#include <vector> -#include <string> -#include "pe_structures.h" -#include "pe_directory.h" -#include "pe_base.h" - -namespace pe_bliss -{ -//Class representing imported function -class imported_function -{ -public: - //Default constructor - imported_function(); - - //Returns true if imported function has name (and hint) - bool has_name() const; - //Returns name of function - const std::string& get_name() const; - //Returns hint - uint16_t get_hint() const; - //Returns ordinal of function - uint16_t get_ordinal() const; - - //Returns IAT entry VA (usable if image has both IAT and original IAT and is bound) - uint64_t get_iat_va() const; - -public: //Setters do not change everything inside image, they are used by PE class - //You also can use them to rebuild image imports - //Sets name of function - void set_name(const std::string& name); - //Sets hint - void set_hint(uint16_t hint); - //Sets ordinal - void set_ordinal(uint16_t ordinal); - - //Sets IAT entry VA (usable if image has both IAT and original IAT and is bound) - void set_iat_va(uint64_t rva); - -private: - std::string name_; //Function name - uint16_t hint_; //Hint - uint16_t ordinal_; //Ordinal - uint64_t iat_va_; -}; - -//Class representing imported library information -class import_library -{ -public: - typedef std::vector<imported_function> imported_list; - -public: - //Default constructor - import_library(); - - //Returns name of library - const std::string& get_name() const; - //Returns RVA to Import Address Table (IAT) - uint32_t get_rva_to_iat() const; - //Returns RVA to Original Import Address Table (Original IAT) - uint32_t get_rva_to_original_iat() const; - //Returns timestamp - uint32_t get_timestamp() const; - - //Returns imported functions list - const imported_list& get_imported_functions() const; - -public: //Setters do not change everything inside image, they are used by PE class - //You also can use them to rebuild image imports - //Sets name of library - void set_name(const std::string& name); - //Sets RVA to Import Address Table (IAT) - void set_rva_to_iat(uint32_t rva_to_iat); - //Sets RVA to Original Import Address Table (Original IAT) - void set_rva_to_original_iat(uint32_t rva_to_original_iat); - //Sets timestamp - void set_timestamp(uint32_t timestamp); - - //Adds imported function - void add_import(const imported_function& func); - //Clears imported functions list - void clear_imports(); - -private: - std::string name_; //Library name - uint32_t rva_to_iat_; //RVA to IAT - uint32_t rva_to_original_iat_; //RVA to original IAT - uint32_t timestamp_; //DLL TimeStamp - - imported_list imports_; -}; - -//Simple import directory rebuilder -//Class representing import rebuilder advanced settings -class import_rebuilder_settings -{ -public: - //Default constructor - //Default constructor - //If set_to_pe_headers = true, IMAGE_DIRECTORY_ENTRY_IMPORT entry will be reset - //to new value after import rebuilding - //If auto_zero_directory_entry_iat = true, IMAGE_DIRECTORY_ENTRY_IAT will be set to zero - //IMAGE_DIRECTORY_ENTRY_IAT is used by loader to temporarily make section, where IMAGE_DIRECTORY_ENTRY_IAT RVA points, writeable - //to be able to modify IAT thunks - explicit import_rebuilder_settings(bool set_to_pe_headers = true, bool auto_zero_directory_entry_iat = false); - - //Returns offset from section start where import directory data will be placed - uint32_t get_offset_from_section_start() const; - //Returns true if Original import address table (IAT) will be rebuilt - bool build_original_iat() const; - - //Returns true if Original import address and import address tables will not be rebuilt, - //works only if import descriptor IAT (and orig.IAT, if present) RVAs are not zero - bool save_iat_and_original_iat_rvas() const; - //Returns true if Original import address and import address tables contents will be rewritten - //works only if import descriptor IAT (and orig.IAT, if present) RVAs are not zero - //and save_iat_and_original_iat_rvas is true - bool rewrite_iat_and_original_iat_contents() const; - - //Returns true if original missing IATs will be rebuilt - //(only if IATs are saved) - bool fill_missing_original_iats() const; - //Returns true if PE headers should be updated automatically after rebuilding of imports - bool auto_set_to_pe_headers() const; - //Returns true if IMAGE_DIRECTORY_ENTRY_IAT must be zeroed, works only if auto_set_to_pe_headers = true - bool zero_directory_entry_iat() const; - - //Returns true if the last section should be stripped automatically, if imports are inside it - bool auto_strip_last_section_enabled() const; - -public: //Setters - //Sets offset from section start where import directory data will be placed - void set_offset_from_section_start(uint32_t offset); - //Sets if Original import address table (IAT) will be rebuilt - void build_original_iat(bool enable); - //Sets if Original import address and import address tables will not be rebuilt, - //works only if import descriptor IAT (and orig.IAT, if present) RVAs are not zero - //enable_rewrite_iat_and_original_iat_contents sets if Original import address and import address tables contents will be rewritten - //works only if import descriptor IAT (and orig.IAT, if present) RVAs are not zero - //and save_iat_and_original_iat_rvas is true - void save_iat_and_original_iat_rvas(bool enable, bool enable_rewrite_iat_and_original_iat_contents = false); - //Sets if original missing IATs will be rebuilt - //(only if IATs are saved) - void fill_missing_original_iats(bool enable); - //Sets if PE headers should be updated automatically after rebuilding of imports - void auto_set_to_pe_headers(bool enable); - //Sets if IMAGE_DIRECTORY_ENTRY_IAT must be zeroed, works only if auto_set_to_pe_headers = true - void zero_directory_entry_iat(bool enable); - - //Sets if the last section should be stripped automatically, if imports are inside it, default true - void enable_auto_strip_last_section(bool enable); - -private: - uint32_t offset_from_section_start_; - bool build_original_iat_; - bool save_iat_and_original_iat_rvas_; - bool fill_missing_original_iats_; - bool set_to_pe_headers_; - bool zero_directory_entry_iat_; - bool rewrite_iat_and_original_iat_contents_; - bool auto_strip_last_section_; -}; - -typedef std::vector<import_library> imported_functions_list; - - -//Returns imported functions list with related libraries info -const imported_functions_list get_imported_functions(const pe_base& pe); - -template<typename PEClassType> -const imported_functions_list get_imported_functions_base(const pe_base& pe); - - -//You can get all image imports with get_imported_functions() function -//You can use returned value to, for example, add new imported library with some functions -//to the end of list of imported libraries -//To keep PE file working, rebuild its imports with save_iat_and_original_iat_rvas = true (default) -//Don't add new imported functions to existing imported library entries, because this can cause -//rewriting of some used memory (or other IAT/orig.IAT fields) by system loader -//The safest way is just adding import libraries with functions to the end of imported_functions_list array -const image_directory rebuild_imports(pe_base& pe, const imported_functions_list& imports, section& import_section, const import_rebuilder_settings& import_settings = import_rebuilder_settings()); - -template<typename PEClassType> -const image_directory rebuild_imports_base(pe_base& pe, const imported_functions_list& imports, section& import_section, const import_rebuilder_settings& import_settings = import_rebuilder_settings()); -} diff --git a/tools/pe_bliss/pe_load_config.cpp b/tools/pe_bliss/pe_load_config.cpp deleted file mode 100644 index c05895fecd..0000000000 --- a/tools/pe_bliss/pe_load_config.cpp +++ /dev/null @@ -1,557 +0,0 @@ -/*************************************************************************/ -/* Copyright (c) 2015 dx, http://kaimi.ru */ -/* */ -/* Permission is hereby granted, free of charge, to any person */ -/* obtaining a copy of this software and associated documentation */ -/* files (the "Software"), to deal in the Software without */ -/* restriction, including without limitation the rights to use, */ -/* copy, modify, merge, publish, distribute, sublicense, and/or */ -/* sell copies of the Software, and to permit persons to whom the */ -/* Software is furnished to do so, subject to the following conditions: */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#include <algorithm> -#include <string.h> -#include "pe_load_config.h" -#include "pe_properties_generic.h" - -namespace pe_bliss -{ -using namespace pe_win; - -//IMAGE CONFIG -//Default constructor -image_config_info::image_config_info() - :time_stamp_(0), - major_version_(0), minor_version_(0), - global_flags_clear_(0), global_flags_set_(0), - critical_section_default_timeout_(0), - decommit_free_block_threshold_(0), decommit_total_free_threshold_(0), - lock_prefix_table_va_(0), - max_allocation_size_(0), - virtual_memory_threshold_(0), - process_affinity_mask_(0), - process_heap_flags_(0), - service_pack_version_(0), - edit_list_va_(0), - security_cookie_va_(0), - se_handler_table_va_(0), - se_handler_count_(0) -{} - -//Constructors from PE structures -template<typename ConfigStructure> -image_config_info::image_config_info(const ConfigStructure& info) - :time_stamp_(info.TimeDateStamp), - major_version_(info.MajorVersion), minor_version_(info.MinorVersion), - global_flags_clear_(info.GlobalFlagsClear), global_flags_set_(info.GlobalFlagsSet), - critical_section_default_timeout_(info.CriticalSectionDefaultTimeout), - decommit_free_block_threshold_(info.DeCommitFreeBlockThreshold), decommit_total_free_threshold_(info.DeCommitTotalFreeThreshold), - lock_prefix_table_va_(info.LockPrefixTable), - max_allocation_size_(info.MaximumAllocationSize), - virtual_memory_threshold_(info.VirtualMemoryThreshold), - process_affinity_mask_(info.ProcessAffinityMask), - process_heap_flags_(info.ProcessHeapFlags), - service_pack_version_(info.CSDVersion), - edit_list_va_(info.EditList), - security_cookie_va_(info.SecurityCookie), - se_handler_table_va_(info.SEHandlerTable), - se_handler_count_(info.SEHandlerCount) -{} - -//Instantiate template constructor with needed structures -template image_config_info::image_config_info(const image_load_config_directory32& info); -template image_config_info::image_config_info(const image_load_config_directory64& info); - -//Returns the date and time stamp value -uint32_t image_config_info::get_time_stamp() const -{ - return time_stamp_; -} - -//Returns major version number -uint16_t image_config_info::get_major_version() const -{ - return major_version_; -} - -//Returns minor version number -uint16_t image_config_info::get_minor_version() const -{ - return minor_version_; -} - -//Returns clear global flags -uint32_t image_config_info::get_global_flags_clear() const -{ - return global_flags_clear_; -} - -//Returns set global flags -uint32_t image_config_info::get_global_flags_set() const -{ - return global_flags_set_; -} - -//Returns critical section default timeout -uint32_t image_config_info::get_critical_section_default_timeout() const -{ - return critical_section_default_timeout_; -} - -//Get the size of the minimum block that -//must be freed before it is freed (de-committed), in bytes -uint64_t image_config_info::get_decommit_free_block_threshold() const -{ - return decommit_free_block_threshold_; -} - -//Returns the size of the minimum total memory -//that must be freed in the process heap before it is freed (de-committed), in bytes -uint64_t image_config_info::get_decommit_total_free_threshold() const -{ - return decommit_total_free_threshold_; -} - -//Returns VA of a list of addresses where the LOCK prefix is used -uint64_t image_config_info::get_lock_prefix_table_va() const -{ - return lock_prefix_table_va_; -} - -//Returns the maximum allocation size, in bytes -uint64_t image_config_info::get_max_allocation_size() const -{ - return max_allocation_size_; -} - -//Returns the maximum block size that can be allocated from heap segments, in bytes -uint64_t image_config_info::get_virtual_memory_threshold() const -{ - return virtual_memory_threshold_; -} - -//Returns process affinity mask -uint64_t image_config_info::get_process_affinity_mask() const -{ - return process_affinity_mask_; -} - -//Returns process heap flags -uint32_t image_config_info::get_process_heap_flags() const -{ - return process_heap_flags_; -} - -//Returns service pack version (CSDVersion) -uint16_t image_config_info::get_service_pack_version() const -{ - return service_pack_version_; -} - -//Returns VA of edit list (reserved by system) -uint64_t image_config_info::get_edit_list_va() const -{ - return edit_list_va_; -} - -//Returns a pointer to a cookie that is used by Visual C++ or GS implementation -uint64_t image_config_info::get_security_cookie_va() const -{ - return security_cookie_va_; -} - -//Returns VA of the sorted table of RVAs of each valid, unique handler in the image -uint64_t image_config_info::get_se_handler_table_va() const -{ - return se_handler_table_va_; -} - -//Returns the count of unique handlers in the table -uint64_t image_config_info::get_se_handler_count() const -{ - return se_handler_count_; -} - -//Returns SE Handler RVA list -const image_config_info::se_handler_list& image_config_info::get_se_handler_rvas() const -{ - return se_handlers_; -} - -//Returns Lock Prefix RVA list -const image_config_info::lock_prefix_rva_list& image_config_info::get_lock_prefix_rvas() const -{ - return lock_prefixes_; -} - -//Adds SE Handler RVA to list -void image_config_info::add_se_handler_rva(uint32_t rva) -{ - se_handlers_.push_back(rva); -} - -//Clears SE Handler list -void image_config_info::clear_se_handler_list() -{ - se_handlers_.clear(); -} - -//Adds Lock Prefix RVA to list -void image_config_info::add_lock_prefix_rva(uint32_t rva) -{ - lock_prefixes_.push_back(rva); -} - -//Clears Lock Prefix list -void image_config_info::clear_lock_prefix_list() -{ - lock_prefixes_.clear(); -} - -//Sets the date and time stamp value -void image_config_info::set_time_stamp(uint32_t time_stamp) -{ - time_stamp_ = time_stamp; -} - -//Sets major version number -void image_config_info::set_major_version(uint16_t major_version) -{ - major_version_ = major_version; -} - -//Sets minor version number -void image_config_info::set_minor_version(uint16_t minor_version) -{ - minor_version_ = minor_version; -} - -//Sets clear global flags -void image_config_info::set_global_flags_clear(uint32_t global_flags_clear) -{ - global_flags_clear_ = global_flags_clear; -} - -//Sets set global flags -void image_config_info::set_global_flags_set(uint32_t global_flags_set) -{ - global_flags_set_ = global_flags_set; -} - -//Sets critical section default timeout -void image_config_info::set_critical_section_default_timeout(uint32_t critical_section_default_timeout) -{ - critical_section_default_timeout_ = critical_section_default_timeout; -} - -//Sets the size of the minimum block that -//must be freed before it is freed (de-committed), in bytes -void image_config_info::set_decommit_free_block_threshold(uint64_t decommit_free_block_threshold) -{ - decommit_free_block_threshold_ = decommit_free_block_threshold; -} - -//Sets the size of the minimum total memory -//that must be freed in the process heap before it is freed (de-committed), in bytes -void image_config_info::set_decommit_total_free_threshold(uint64_t decommit_total_free_threshold) -{ - decommit_total_free_threshold_ = decommit_total_free_threshold; -} - -//Sets VA of a list of addresses where the LOCK prefix is used -//If you rebuild this list, VA will be re-assigned automatically -void image_config_info::set_lock_prefix_table_va(uint64_t lock_prefix_table_va) -{ - lock_prefix_table_va_ = lock_prefix_table_va; -} - -//Sets the maximum allocation size, in bytes -void image_config_info::set_max_allocation_size(uint64_t max_allocation_size) -{ - max_allocation_size_ = max_allocation_size; -} - -//Sets the maximum block size that can be allocated from heap segments, in bytes -void image_config_info::set_virtual_memory_threshold(uint64_t virtual_memory_threshold) -{ - virtual_memory_threshold_ = virtual_memory_threshold; -} - -//Sets process affinity mask -void image_config_info::set_process_affinity_mask(uint64_t process_affinity_mask) -{ - process_affinity_mask_ = process_affinity_mask; -} - -//Sets process heap flags -void image_config_info::set_process_heap_flags(uint32_t process_heap_flags) -{ - process_heap_flags_ = process_heap_flags; -} - -//Sets service pack version (CSDVersion) -void image_config_info::set_service_pack_version(uint16_t service_pack_version) -{ - service_pack_version_ = service_pack_version; -} - -//Sets VA of edit list (reserved by system) -void image_config_info::set_edit_list_va(uint64_t edit_list_va) -{ - edit_list_va_ = edit_list_va; -} - -//Sets a pointer to a cookie that is used by Visual C++ or GS implementation -void image_config_info::set_security_cookie_va(uint64_t security_cookie_va) -{ - security_cookie_va_ = security_cookie_va; -} - -//Sets VA of the sorted table of RVAs of each valid, unique handler in the image -//If you rebuild this list, VA will be re-assigned automatically -void image_config_info::set_se_handler_table_va(uint64_t se_handler_table_va) -{ - se_handler_table_va_ = se_handler_table_va; -} - -//Returns SE Handler RVA list -image_config_info::se_handler_list& image_config_info::get_se_handler_rvas() -{ - return se_handlers_; -} - -//Returns Lock Prefix RVA list -image_config_info::lock_prefix_rva_list& image_config_info::get_lock_prefix_rvas() -{ - return lock_prefixes_; -} - -//Returns image config info -//If image does not have config info, throws an exception -const image_config_info get_image_config(const pe_base& pe) -{ - return pe.get_pe_type() == pe_type_32 - ? get_image_config_base<pe_types_class_32>(pe) - : get_image_config_base<pe_types_class_64>(pe); -} - -//Image config rebuilder -const image_directory rebuild_image_config(pe_base& pe, const image_config_info& info, section& image_config_section, uint32_t offset_from_section_start, bool write_se_handlers, bool write_lock_prefixes, bool save_to_pe_header, bool auto_strip_last_section) -{ - return pe.get_pe_type() == pe_type_32 - ? rebuild_image_config_base<pe_types_class_32>(pe, info, image_config_section, offset_from_section_start, write_se_handlers, write_lock_prefixes, save_to_pe_header, auto_strip_last_section) - : rebuild_image_config_base<pe_types_class_64>(pe, info, image_config_section, offset_from_section_start, write_se_handlers, write_lock_prefixes, save_to_pe_header, auto_strip_last_section); -} - - -//Returns image config info -//If image does not have config info, throws an exception -template<typename PEClassType> -const image_config_info get_image_config_base(const pe_base& pe) -{ - //Check if image has config directory - if(!pe.has_config()) - throw pe_exception("Image does not have load config directory", pe_exception::directory_does_not_exist); - - //Get load config structure - typename PEClassType::ConfigStruct config_info = pe.section_data_from_rva<typename PEClassType::ConfigStruct>(pe.get_directory_rva(image_directory_entry_load_config), section_data_virtual); - - //Check size of config directory - if(config_info.Size != sizeof(config_info)) - throw pe_exception("Incorrect (or old) load config directory", pe_exception::incorrect_config_directory); - - //Fill return structure - image_config_info ret(config_info); - - //Check possible overflow - if(config_info.SEHandlerCount >= pe_utils::max_dword / sizeof(uint32_t) - || config_info.SEHandlerTable >= static_cast<typename PEClassType::BaseSize>(-1) - config_info.SEHandlerCount * sizeof(uint32_t)) - throw pe_exception("Incorrect load config directory", pe_exception::incorrect_config_directory); - - //Read sorted SE handler RVA list (if any) - for(typename PEClassType::BaseSize i = 0; i != config_info.SEHandlerCount; ++i) - ret.add_se_handler_rva(pe.section_data_from_va<uint32_t>(static_cast<typename PEClassType::BaseSize>(config_info.SEHandlerTable + i * sizeof(uint32_t)))); - - if(config_info.LockPrefixTable) - { - //Read Lock Prefix VA list (if any) - unsigned long current = 0; - while(true) - { - typename PEClassType::BaseSize lock_prefix_va = pe.section_data_from_va<typename PEClassType::BaseSize>(static_cast<typename PEClassType::BaseSize>(config_info.LockPrefixTable + current * sizeof(typename PEClassType::BaseSize))); - if(!lock_prefix_va) - break; - - ret.add_lock_prefix_rva(pe.va_to_rva(lock_prefix_va)); - - ++current; - } - } - - return ret; -} - -//Image config directory rebuilder -//auto_strip_last_section - if true and TLS are placed in the last section, it will be automatically stripped -//If write_se_handlers = true, SE Handlers list will be written just after image config directory structure -//If write_lock_prefixes = true, Lock Prefixes address list will be written just after image config directory structure -template<typename PEClassType> -const image_directory rebuild_image_config_base(pe_base& pe, const image_config_info& info, section& image_config_section, uint32_t offset_from_section_start, bool write_se_handlers, bool write_lock_prefixes, bool save_to_pe_header, bool auto_strip_last_section) -{ - //Check that image_config_section is attached to this PE image - if(!pe.section_attached(image_config_section)) - throw pe_exception("Image Config section must be attached to PE file", pe_exception::section_is_not_attached); - - uint32_t alignment = pe_utils::align_up(offset_from_section_start, sizeof(typename PEClassType::BaseSize)) - offset_from_section_start; - - uint32_t needed_size = sizeof(typename PEClassType::ConfigStruct); //Calculate needed size for Image Config table - - uint32_t image_config_data_pos = offset_from_section_start + alignment; - - uint32_t current_pos_of_se_handlers = 0; - uint32_t current_pos_of_lock_prefixes = 0; - - if(write_se_handlers) - { - current_pos_of_se_handlers = needed_size + image_config_data_pos; - needed_size += static_cast<uint32_t>(info.get_se_handler_rvas().size()) * sizeof(uint32_t); //RVAs of SE Handlers - } - - if(write_lock_prefixes) - { - current_pos_of_lock_prefixes = needed_size + image_config_data_pos; - needed_size += static_cast<uint32_t>((info.get_lock_prefix_rvas().size() + 1) * sizeof(typename PEClassType::BaseSize)); //VAs of Lock Prefixes (and ending null element) - } - - //Check if image_config_section is last one. If it's not, check if there's enough place for Image Config data - if(&image_config_section != &*(pe.get_image_sections().end() - 1) && - (image_config_section.empty() || pe_utils::align_up(image_config_section.get_size_of_raw_data(), pe.get_file_alignment()) < needed_size + image_config_data_pos)) - throw pe_exception("Insufficient space for TLS directory", pe_exception::insufficient_space); - - std::string& raw_data = image_config_section.get_raw_data(); - - //This will be done only if image_config_section is the last section of image or for section with unaligned raw length of data - if(raw_data.length() < needed_size + image_config_data_pos) - raw_data.resize(needed_size + image_config_data_pos); //Expand section raw data - - //Create and fill Image Config structure - typename PEClassType::ConfigStruct image_config_section_struct = {0}; - image_config_section_struct.Size = sizeof(image_config_section_struct); - image_config_section_struct.TimeDateStamp = info.get_time_stamp(); - image_config_section_struct.MajorVersion = info.get_major_version(); - image_config_section_struct.MinorVersion = info.get_minor_version(); - image_config_section_struct.GlobalFlagsClear = info.get_global_flags_clear(); - image_config_section_struct.GlobalFlagsSet = info.get_global_flags_set(); - image_config_section_struct.CriticalSectionDefaultTimeout = info.get_critical_section_default_timeout(); - image_config_section_struct.DeCommitFreeBlockThreshold = static_cast<typename PEClassType::BaseSize>(info.get_decommit_free_block_threshold()); - image_config_section_struct.DeCommitTotalFreeThreshold = static_cast<typename PEClassType::BaseSize>(info.get_decommit_total_free_threshold()); - image_config_section_struct.MaximumAllocationSize = static_cast<typename PEClassType::BaseSize>(info.get_max_allocation_size()); - image_config_section_struct.VirtualMemoryThreshold = static_cast<typename PEClassType::BaseSize>(info.get_virtual_memory_threshold()); - image_config_section_struct.ProcessHeapFlags = info.get_process_heap_flags(); - image_config_section_struct.ProcessAffinityMask = static_cast<typename PEClassType::BaseSize>(info.get_process_affinity_mask()); - image_config_section_struct.CSDVersion = info.get_service_pack_version(); - image_config_section_struct.EditList = static_cast<typename PEClassType::BaseSize>(info.get_edit_list_va()); - image_config_section_struct.SecurityCookie = static_cast<typename PEClassType::BaseSize>(info.get_security_cookie_va()); - image_config_section_struct.SEHandlerCount = static_cast<typename PEClassType::BaseSize>(info.get_se_handler_rvas().size()); - - - if(write_se_handlers) - { - if(info.get_se_handler_rvas().empty()) - { - write_se_handlers = false; - image_config_section_struct.SEHandlerTable = 0; - } - else - { - typename PEClassType::BaseSize va; - pe.rva_to_va(pe.rva_from_section_offset(image_config_section, current_pos_of_se_handlers), va); - image_config_section_struct.SEHandlerTable = va; - } - } - else - { - image_config_section_struct.SEHandlerTable = static_cast<typename PEClassType::BaseSize>(info.get_se_handler_table_va()); - } - - if(write_lock_prefixes) - { - if(info.get_lock_prefix_rvas().empty()) - { - write_lock_prefixes = false; - image_config_section_struct.LockPrefixTable = 0; - } - else - { - typename PEClassType::BaseSize va; - pe.rva_to_va(pe.rva_from_section_offset(image_config_section, current_pos_of_lock_prefixes), va); - image_config_section_struct.LockPrefixTable = va; - } - } - else - { - image_config_section_struct.LockPrefixTable = static_cast<typename PEClassType::BaseSize>(info.get_lock_prefix_table_va()); - } - - //Write image config section - memcpy(&raw_data[image_config_data_pos], &image_config_section_struct, sizeof(image_config_section_struct)); - - if(write_se_handlers) - { - //Sort SE Handlers list - image_config_info::se_handler_list sorted_list = info.get_se_handler_rvas(); - std::sort(sorted_list.begin(), sorted_list.end()); - - //Write SE Handlers table - for(image_config_info::se_handler_list::const_iterator it = sorted_list.begin(); it != sorted_list.end(); ++it) - { - uint32_t se_handler_rva = *it; - memcpy(&raw_data[current_pos_of_se_handlers], &se_handler_rva, sizeof(se_handler_rva)); - current_pos_of_se_handlers += sizeof(se_handler_rva); - } - } - - if(write_lock_prefixes) - { - //Write Lock Prefixes VA list - for(image_config_info::lock_prefix_rva_list::const_iterator it = info.get_lock_prefix_rvas().begin(); it != info.get_lock_prefix_rvas().end(); ++it) - { - typename PEClassType::BaseSize lock_prefix_va; - pe.rva_to_va(*it, lock_prefix_va); - memcpy(&raw_data[current_pos_of_lock_prefixes], &lock_prefix_va, sizeof(lock_prefix_va)); - current_pos_of_lock_prefixes += sizeof(lock_prefix_va); - } - - { - //Ending null VA - typename PEClassType::BaseSize lock_prefix_va = 0; - memcpy(&raw_data[current_pos_of_lock_prefixes], &lock_prefix_va, sizeof(lock_prefix_va)); - } - } - - //Adjust section raw and virtual sizes - pe.recalculate_section_sizes(image_config_section, auto_strip_last_section); - - image_directory ret(pe.rva_from_section_offset(image_config_section, image_config_data_pos), sizeof(typename PEClassType::ConfigStruct)); - - //If auto-rewrite of PE headers is required - if(save_to_pe_header) - { - pe.set_directory_rva(image_directory_entry_load_config, ret.get_rva()); - pe.set_directory_size(image_directory_entry_load_config, ret.get_size()); - } - - return ret; -} - -} diff --git a/tools/pe_bliss/pe_load_config.h b/tools/pe_bliss/pe_load_config.h deleted file mode 100644 index cb24072de7..0000000000 --- a/tools/pe_bliss/pe_load_config.h +++ /dev/null @@ -1,184 +0,0 @@ -/*************************************************************************/ -/* Copyright (c) 2015 dx, http://kaimi.ru */ -/* */ -/* Permission is hereby granted, free of charge, to any person */ -/* obtaining a copy of this software and associated documentation */ -/* files (the "Software"), to deal in the Software without */ -/* restriction, including without limitation the rights to use, */ -/* copy, modify, merge, publish, distribute, sublicense, and/or */ -/* sell copies of the Software, and to permit persons to whom the */ -/* Software is furnished to do so, subject to the following conditions: */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#pragma once -#include <vector> -#include "pe_structures.h" -#include "pe_base.h" -#include "pe_directory.h" - -namespace pe_bliss -{ -//Class representing image configuration information -class image_config_info -{ -public: - typedef std::vector<uint32_t> se_handler_list; - typedef std::vector<uint32_t> lock_prefix_rva_list; - -public: - //Default constructor - image_config_info(); - //Constructors from PE structures (no checks) - template<typename ConfigStructure> - explicit image_config_info(const ConfigStructure& info); - - //Returns the date and time stamp value - uint32_t get_time_stamp() const; - //Returns major version number - uint16_t get_major_version() const; - //Returns minor version number - uint16_t get_minor_version() const; - //Returns clear global flags - uint32_t get_global_flags_clear() const; - //Returns set global flags - uint32_t get_global_flags_set() const; - //Returns critical section default timeout - uint32_t get_critical_section_default_timeout() const; - //Get the size of the minimum block that - //must be freed before it is freed (de-committed), in bytes - uint64_t get_decommit_free_block_threshold() const; - //Returns the size of the minimum total memory - //that must be freed in the process heap before it is freed (de-committed), in bytes - uint64_t get_decommit_total_free_threshold() const; - //Returns VA of a list of addresses where the LOCK prefix is used - uint64_t get_lock_prefix_table_va() const; - //Returns the maximum allocation size, in bytes - uint64_t get_max_allocation_size() const; - //Returns the maximum block size that can be allocated from heap segments, in bytes - uint64_t get_virtual_memory_threshold() const; - //Returns process affinity mask - uint64_t get_process_affinity_mask() const; - //Returns process heap flags - uint32_t get_process_heap_flags() const; - //Returns service pack version (CSDVersion) - uint16_t get_service_pack_version() const; - //Returns VA of edit list (reserved by system) - uint64_t get_edit_list_va() const; - //Returns a pointer to a cookie that is used by Visual C++ or GS implementation - uint64_t get_security_cookie_va() const; - //Returns VA of the sorted table of RVAs of each valid, unique handler in the image - uint64_t get_se_handler_table_va() const; - //Returns the count of unique handlers in the table - uint64_t get_se_handler_count() const; - - //Returns SE Handler RVA list - const se_handler_list& get_se_handler_rvas() const; - - //Returns Lock Prefix RVA list - const lock_prefix_rva_list& get_lock_prefix_rvas() const; - -public: //These functions do not change everything inside image, they are used by PE class - //Also you can use these functions to rebuild image config directory - - //Adds SE Handler RVA to list - void add_se_handler_rva(uint32_t rva); - //Clears SE Handler list - void clear_se_handler_list(); - - //Adds Lock Prefix RVA to list - void add_lock_prefix_rva(uint32_t rva); - //Clears Lock Prefix list - void clear_lock_prefix_list(); - - //Sets the date and time stamp value - void set_time_stamp(uint32_t time_stamp); - //Sets major version number - void set_major_version(uint16_t major_version); - //Sets minor version number - void set_minor_version(uint16_t minor_version); - //Sets clear global flags - void set_global_flags_clear(uint32_t global_flags_clear); - //Sets set global flags - void set_global_flags_set(uint32_t global_flags_set); - //Sets critical section default timeout - void set_critical_section_default_timeout(uint32_t critical_section_default_timeout); - //Sets the size of the minimum block that - //must be freed before it is freed (de-committed), in bytes - void set_decommit_free_block_threshold(uint64_t decommit_free_block_threshold); - //Sets the size of the minimum total memory - //that must be freed in the process heap before it is freed (de-committed), in bytes - void set_decommit_total_free_threshold(uint64_t decommit_total_free_threshold); - //Sets VA of a list of addresses where the LOCK prefix is used - //If you rebuild this list, VA will be re-assigned automatically - void set_lock_prefix_table_va(uint64_t lock_prefix_table_va); - //Sets the maximum allocation size, in bytes - void set_max_allocation_size(uint64_t max_allocation_size); - //Sets the maximum block size that can be allocated from heap segments, in bytes - void set_virtual_memory_threshold(uint64_t virtual_memory_threshold); - //Sets process affinity mask - void set_process_affinity_mask(uint64_t process_affinity_mask); - //Sets process heap flags - void set_process_heap_flags(uint32_t process_heap_flags); - //Sets service pack version (CSDVersion) - void set_service_pack_version(uint16_t service_pack_version); - //Sets VA of edit list (reserved by system) - void set_edit_list_va(uint64_t edit_list_va); - //Sets a pointer to a cookie that is used by Visual C++ or GS implementation - void set_security_cookie_va(uint64_t security_cookie_va); - //Sets VA of the sorted table of RVAs of each valid, unique handler in the image - //If you rebuild this list, VA will be re-assigned automatically - void set_se_handler_table_va(uint64_t se_handler_table_va); - - //Returns SE Handler RVA list - se_handler_list& get_se_handler_rvas(); - - //Returns Lock Prefix RVA list - lock_prefix_rva_list& get_lock_prefix_rvas(); - -private: - uint32_t time_stamp_; - uint16_t major_version_, minor_version_; - uint32_t global_flags_clear_, global_flags_set_; - uint32_t critical_section_default_timeout_; - uint64_t decommit_free_block_threshold_, decommit_total_free_threshold_; - uint64_t lock_prefix_table_va_; - uint64_t max_allocation_size_; - uint64_t virtual_memory_threshold_; - uint64_t process_affinity_mask_; - uint32_t process_heap_flags_; - uint16_t service_pack_version_; - uint64_t edit_list_va_; - uint64_t security_cookie_va_; - uint64_t se_handler_table_va_; - uint64_t se_handler_count_; - - se_handler_list se_handlers_; - lock_prefix_rva_list lock_prefixes_; -}; - -//Returns image config info -//If image does not have config info, throws an exception -const image_config_info get_image_config(const pe_base& pe); - -template<typename PEClassType> -const image_config_info get_image_config_base(const pe_base& pe); - - -//Image config directory rebuilder -//auto_strip_last_section - if true and TLS are placed in the last section, it will be automatically stripped -//If write_se_handlers = true, SE Handlers list will be written just after image config directory structure -//If write_lock_prefixes = true, Lock Prefixes address list will be written just after image config directory structure -const image_directory rebuild_image_config(pe_base& pe, const image_config_info& info, section& image_config_section, uint32_t offset_from_section_start = 0, bool write_se_handlers = true, bool write_lock_prefixes = true, bool save_to_pe_header = true, bool auto_strip_last_section = true); - -template<typename PEClassType> -const image_directory rebuild_image_config_base(pe_base& pe, const image_config_info& info, section& image_config_section, uint32_t offset_from_section_start = 0, bool write_se_handlers = true, bool write_lock_prefixes = true, bool save_to_pe_header = true, bool auto_strip_last_section = true); -} diff --git a/tools/pe_bliss/pe_properties.cpp b/tools/pe_bliss/pe_properties.cpp deleted file mode 100644 index 8d1c2eac43..0000000000 --- a/tools/pe_bliss/pe_properties.cpp +++ /dev/null @@ -1,41 +0,0 @@ -/*************************************************************************/ -/* Copyright (c) 2015 dx, http://kaimi.ru */ -/* */ -/* Permission is hereby granted, free of charge, to any person */ -/* obtaining a copy of this software and associated documentation */ -/* files (the "Software"), to deal in the Software without */ -/* restriction, including without limitation the rights to use, */ -/* copy, modify, merge, publish, distribute, sublicense, and/or */ -/* sell copies of the Software, and to permit persons to whom the */ -/* Software is furnished to do so, subject to the following conditions: */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#include "pe_properties.h" - -namespace pe_bliss -{ -//Destructor -pe_properties::~pe_properties() -{} - -//Clears PE characteristics flag -void pe_properties::clear_characteristics_flags(uint16_t flags) -{ - set_characteristics(get_characteristics() & ~flags); -} - -//Sets PE characteristics flag -void pe_properties::set_characteristics_flags(uint16_t flags) -{ - set_characteristics(get_characteristics() | flags); -} -} diff --git a/tools/pe_bliss/pe_properties.h b/tools/pe_bliss/pe_properties.h deleted file mode 100644 index 1db163e8b1..0000000000 --- a/tools/pe_bliss/pe_properties.h +++ /dev/null @@ -1,236 +0,0 @@ -/*************************************************************************/ -/* Copyright (c) 2015 dx, http://kaimi.ru */ -/* */ -/* Permission is hereby granted, free of charge, to any person */ -/* obtaining a copy of this software and associated documentation */ -/* files (the "Software"), to deal in the Software without */ -/* restriction, including without limitation the rights to use, */ -/* copy, modify, merge, publish, distribute, sublicense, and/or */ -/* sell copies of the Software, and to permit persons to whom the */ -/* Software is furnished to do so, subject to the following conditions: */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#pragma once -#include <memory> -#include "pe_structures.h" - -namespace pe_bliss -{ -class pe_properties -{ -public: //Constructors - virtual std::auto_ptr<pe_properties> duplicate() const = 0; - - //Fills properly PE structures - virtual void create_pe(uint32_t section_alignment, uint16_t subsystem) = 0; - -public: - //Destructor - virtual ~pe_properties(); - - -public: //DIRECTORIES - //Returns true if directory exists - virtual bool directory_exists(uint32_t id) const = 0; - - //Removes directory - virtual void remove_directory(uint32_t id) = 0; - - //Returns directory RVA - virtual uint32_t get_directory_rva(uint32_t id) const = 0; - //Returns directory size - virtual uint32_t get_directory_size(uint32_t id) const = 0; - - //Sets directory RVA (just a value of PE header, no moving occurs) - virtual void set_directory_rva(uint32_t id, uint32_t rva) = 0; - //Sets directory size (just a value of PE header, no moving occurs) - virtual void set_directory_size(uint32_t id, uint32_t size) = 0; - - //Strips only zero DATA_DIRECTORY entries to count = min_count - //Returns resulting number of data directories - //strip_iat_directory - if true, even not empty IAT directory will be stripped - virtual uint32_t strip_data_directories(uint32_t min_count = 1, bool strip_iat_directory = true) = 0; - - -public: //IMAGE - //Returns PE type of this image - virtual pe_type get_pe_type() const = 0; - - -public: //PE HEADER - //Returns image base for PE32 and PE64 respectively - virtual uint32_t get_image_base_32() const = 0; - virtual uint64_t get_image_base_64() const = 0; - - //Sets new image base for PE32 - virtual void set_image_base(uint32_t base) = 0; - //Sets new image base for PE32/PE+ - virtual void set_image_base_64(uint64_t base) = 0; - - //Returns image entry point - virtual uint32_t get_ep() const = 0; - //Sets image entry point - virtual void set_ep(uint32_t new_ep) = 0; - - //Returns file alignment - virtual uint32_t get_file_alignment() const = 0; - //Returns section alignment - virtual uint32_t get_section_alignment() const = 0; - - //Sets heap size commit for PE32 and PE64 respectively - virtual void set_heap_size_commit(uint32_t size) = 0; - virtual void set_heap_size_commit(uint64_t size) = 0; - //Sets heap size reserve for PE32 and PE64 respectively - virtual void set_heap_size_reserve(uint32_t size) = 0; - virtual void set_heap_size_reserve(uint64_t size) = 0; - //Sets stack size commit for PE32 and PE64 respectively - virtual void set_stack_size_commit(uint32_t size) = 0; - virtual void set_stack_size_commit(uint64_t size) = 0; - //Sets stack size reserve for PE32 and PE64 respectively - virtual void set_stack_size_reserve(uint32_t size) = 0; - virtual void set_stack_size_reserve(uint64_t size) = 0; - - //Returns heap size commit for PE32 and PE64 respectively - virtual uint32_t get_heap_size_commit_32() const = 0; - virtual uint64_t get_heap_size_commit_64() const = 0; - //Returns heap size reserve for PE32 and PE64 respectively - virtual uint32_t get_heap_size_reserve_32() const = 0; - virtual uint64_t get_heap_size_reserve_64() const = 0; - //Returns stack size commit for PE32 and PE64 respectively - virtual uint32_t get_stack_size_commit_32() const = 0; - virtual uint64_t get_stack_size_commit_64() const = 0; - //Returns stack size reserve for PE32 and PE64 respectively - virtual uint32_t get_stack_size_reserve_32() const = 0; - virtual uint64_t get_stack_size_reserve_64() const = 0; - - //Returns virtual size of image - virtual uint32_t get_size_of_image() const = 0; - - //Returns number of RVA and sizes (number of DATA_DIRECTORY entries) - virtual uint32_t get_number_of_rvas_and_sizes() const = 0; - //Sets number of RVA and sizes (number of DATA_DIRECTORY entries) - virtual void set_number_of_rvas_and_sizes(uint32_t number) = 0; - - //Returns PE characteristics - virtual uint16_t get_characteristics() const = 0; - //Sets PE characteristics - virtual void set_characteristics(uint16_t ch) = 0; - - //Clears PE characteristics flag - void clear_characteristics_flags(uint16_t flags); - //Sets PE characteristics flag - void set_characteristics_flags(uint16_t flags); - - //Returns size of headers - virtual uint32_t get_size_of_headers() const = 0; - - //Returns subsystem - virtual uint16_t get_subsystem() const = 0; - - //Sets subsystem - virtual void set_subsystem(uint16_t subsystem) = 0; - - //Returns size of optional header - virtual uint16_t get_size_of_optional_header() const = 0; - - //Returns PE signature - virtual uint32_t get_pe_signature() const = 0; - - //Returns PE magic value - virtual uint32_t get_magic() const = 0; - - //Returns checksum of PE file from header - virtual uint32_t get_checksum() const = 0; - - //Sets checksum of PE file - virtual void set_checksum(uint32_t checksum) = 0; - - //Returns timestamp of PE file from header - virtual uint32_t get_time_date_stamp() const = 0; - - //Sets timestamp of PE file - virtual void set_time_date_stamp(uint32_t timestamp) = 0; - - //Returns Machine field value of PE file from header - virtual uint16_t get_machine() const = 0; - - //Sets Machine field value of PE file - virtual void set_machine(uint16_t machine) = 0; - - //Returns DLL Characteristics - virtual uint16_t get_dll_characteristics() const = 0; - - //Sets DLL Characteristics - virtual void set_dll_characteristics(uint16_t characteristics) = 0; - - //Sets required operation system version - virtual void set_os_version(uint16_t major, uint16_t minor) = 0; - - //Returns required operation system version (minor word) - virtual uint16_t get_minor_os_version() const = 0; - - //Returns required operation system version (major word) - virtual uint16_t get_major_os_version() const = 0; - - //Sets required subsystem version - virtual void set_subsystem_version(uint16_t major, uint16_t minor) = 0; - - //Returns required subsystem version (minor word) - virtual uint16_t get_minor_subsystem_version() const = 0; - - //Returns required subsystem version (major word) - virtual uint16_t get_major_subsystem_version() const = 0; - -public: //ADDRESS CONVERTIONS - //Virtual Address (VA) to Relative Virtual Address (RVA) convertions - //for PE32 and PE64 respectively - //bound_check checks integer overflow - virtual uint32_t va_to_rva(uint32_t va, bool bound_check = true) const = 0; - virtual uint32_t va_to_rva(uint64_t va, bool bound_check = true) const = 0; - - //Relative Virtual Address (RVA) to Virtual Address (VA) convertions - //for PE32 and PE64 respectively - virtual uint32_t rva_to_va_32(uint32_t rva) const = 0; - virtual uint64_t rva_to_va_64(uint32_t rva) const = 0; - - -public: //SECTIONS - //Returns number of sections - virtual uint16_t get_number_of_sections() const = 0; - -public: - //Sets number of sections - virtual void set_number_of_sections(uint16_t number) = 0; - //Sets virtual size of image - virtual void set_size_of_image(uint32_t size) = 0; - //Sets size of headers - virtual void set_size_of_headers(uint32_t size) = 0; - //Sets size of optional headers - virtual void set_size_of_optional_header(uint16_t size) = 0; - //Returns nt headers data pointer - virtual char* get_nt_headers_ptr() = 0; - //Returns nt headers data pointer - virtual const char* get_nt_headers_ptr() const = 0; - //Returns size of NT header - virtual uint32_t get_sizeof_nt_header() const = 0; - //Returns size of optional headers - virtual uint32_t get_sizeof_opt_headers() const = 0; - //Sets file alignment (no checks) - virtual void set_file_alignment_unchecked(uint32_t alignment) = 0; - //Sets base of code - virtual void set_base_of_code(uint32_t base) = 0; - //Returns base of code - virtual uint32_t get_base_of_code() const = 0; - //Returns needed PE magic for PE or PE+ (from template parameters) - virtual uint32_t get_needed_magic() const = 0; -}; -} diff --git a/tools/pe_bliss/pe_properties_generic.cpp b/tools/pe_bliss/pe_properties_generic.cpp deleted file mode 100644 index bcf6f2047d..0000000000 --- a/tools/pe_bliss/pe_properties_generic.cpp +++ /dev/null @@ -1,645 +0,0 @@ -/*************************************************************************/ -/* Copyright (c) 2015 dx, http://kaimi.ru */ -/* */ -/* Permission is hereby granted, free of charge, to any person */ -/* obtaining a copy of this software and associated documentation */ -/* files (the "Software"), to deal in the Software without */ -/* restriction, including without limitation the rights to use, */ -/* copy, modify, merge, publish, distribute, sublicense, and/or */ -/* sell copies of the Software, and to permit persons to whom the */ -/* Software is furnished to do so, subject to the following conditions: */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#include <string.h> -#include "pe_properties_generic.h" -#include "pe_exception.h" -#include "utils.h" - -namespace pe_bliss -{ -using namespace pe_win; - -//Constructor -template<typename PEClassType> -std::auto_ptr<pe_properties> pe_properties_generic<PEClassType>::duplicate() const -{ - return std::auto_ptr<pe_properties>(new pe_properties_generic<PEClassType>(*this)); -} - -//Fills properly PE structures -template<typename PEClassType> -void pe_properties_generic<PEClassType>::create_pe(uint32_t section_alignment, uint16_t subsystem) -{ - memset(&nt_headers_, 0, sizeof(nt_headers_)); - nt_headers_.Signature = 0x4550; //"PE" - nt_headers_.FileHeader.Machine = 0x14C; //i386 - nt_headers_.FileHeader.SizeOfOptionalHeader = sizeof(nt_headers_.OptionalHeader); - nt_headers_.OptionalHeader.Magic = PEClassType::Id; - nt_headers_.OptionalHeader.ImageBase = 0x400000; - nt_headers_.OptionalHeader.SectionAlignment = section_alignment; - nt_headers_.OptionalHeader.FileAlignment = 0x200; - nt_headers_.OptionalHeader.SizeOfHeaders = 1024; - nt_headers_.OptionalHeader.Subsystem = subsystem; - nt_headers_.OptionalHeader.SizeOfHeapReserve = 0x100000; - nt_headers_.OptionalHeader.SizeOfHeapCommit = 0x1000; - nt_headers_.OptionalHeader.SizeOfStackReserve = 0x100000; - nt_headers_.OptionalHeader.SizeOfStackCommit = 0x1000; - nt_headers_.OptionalHeader.NumberOfRvaAndSizes = 0x10; -} - -//Duplicate -template<typename PEClassType> -pe_properties_generic<PEClassType>::~pe_properties_generic() -{} - -//Returns true if directory exists -template<typename PEClassType> -bool pe_properties_generic<PEClassType>::directory_exists(uint32_t id) const -{ - return (nt_headers_.OptionalHeader.NumberOfRvaAndSizes - 1) >= id && - nt_headers_.OptionalHeader.DataDirectory[id].VirtualAddress; -} - -//Removes directory -template<typename PEClassType> -void pe_properties_generic<PEClassType>::remove_directory(uint32_t id) -{ - if(directory_exists(id)) - { - nt_headers_.OptionalHeader.DataDirectory[id].VirtualAddress = 0; - nt_headers_.OptionalHeader.DataDirectory[id].Size = 0; - - if(id == image_directory_entry_basereloc) - { - set_characteristics_flags(image_file_relocs_stripped); - set_dll_characteristics(get_dll_characteristics() & ~image_dllcharacteristics_dynamic_base); - } - else if(id == image_directory_entry_export) - { - clear_characteristics_flags(image_file_dll); - } - } -} - -//Returns directory RVA -template<typename PEClassType> -uint32_t pe_properties_generic<PEClassType>::get_directory_rva(uint32_t id) const -{ - //Check if directory exists - if(nt_headers_.OptionalHeader.NumberOfRvaAndSizes <= id) - throw pe_exception("Specified directory does not exist", pe_exception::directory_does_not_exist); - - return nt_headers_.OptionalHeader.DataDirectory[id].VirtualAddress; -} - -//Returns directory size -template<typename PEClassType> -void pe_properties_generic<PEClassType>::set_directory_rva(uint32_t id, uint32_t va) -{ - //Check if directory exists - if(nt_headers_.OptionalHeader.NumberOfRvaAndSizes <= id) - throw pe_exception("Specified directory does not exist", pe_exception::directory_does_not_exist); - - nt_headers_.OptionalHeader.DataDirectory[id].VirtualAddress = va; -} - -template<typename PEClassType> -void pe_properties_generic<PEClassType>::set_directory_size(uint32_t id, uint32_t size) -{ - //Check if directory exists - if(nt_headers_.OptionalHeader.NumberOfRvaAndSizes <= id) - throw pe_exception("Specified directory does not exist", pe_exception::directory_does_not_exist); - - nt_headers_.OptionalHeader.DataDirectory[id].Size = size; -} - -//Returns directory size -template<typename PEClassType> -uint32_t pe_properties_generic<PEClassType>::get_directory_size(uint32_t id) const -{ - //Check if directory exists - if(nt_headers_.OptionalHeader.NumberOfRvaAndSizes <= id) - throw pe_exception("Specified directory does not exist", pe_exception::directory_does_not_exist); - - return nt_headers_.OptionalHeader.DataDirectory[id].Size; -} - -//Strips only zero DATA_DIRECTORY entries to count = min_count -//Returns resulting number of data directories -//strip_iat_directory - if true, even not empty IAT directory will be stripped -template<typename PEClassType> -uint32_t pe_properties_generic<PEClassType>::strip_data_directories(uint32_t min_count, bool strip_iat_directory) -{ - int i = nt_headers_.OptionalHeader.NumberOfRvaAndSizes - 1; - - //Enumerate all data directories from the end - for(; i >= 0; i--) - { - //If directory exists, break - if(nt_headers_.OptionalHeader.DataDirectory[i].VirtualAddress && (static_cast<uint32_t>(i) != image_directory_entry_iat || !strip_iat_directory)) - break; - - if(i <= static_cast<int>(min_count) - 2) - break; - } - - if(i == image_numberof_directory_entries - 1) - return image_numberof_directory_entries; - - //Return new number of data directories - return nt_headers_.OptionalHeader.NumberOfRvaAndSizes = i + 1; -} - -//Returns image base for PE32 -template<typename PEClassType> -uint32_t pe_properties_generic<PEClassType>::get_image_base_32() const -{ - return static_cast<uint32_t>(nt_headers_.OptionalHeader.ImageBase); -} - -//Returns image base for PE32/PE64 -template<typename PEClassType> -uint64_t pe_properties_generic<PEClassType>::get_image_base_64() const -{ - return static_cast<uint64_t>(nt_headers_.OptionalHeader.ImageBase); -} - -//Sets new image base -template<typename PEClassType> -void pe_properties_generic<PEClassType>::set_image_base(uint32_t base) -{ - nt_headers_.OptionalHeader.ImageBase = base; -} - -//Sets new image base -template<typename PEClassType> -void pe_properties_generic<PEClassType>::set_image_base_64(uint64_t base) -{ - nt_headers_.OptionalHeader.ImageBase = static_cast<typename PEClassType::BaseSize>(base); -} - -//Returns image entry point -template<typename PEClassType> -uint32_t pe_properties_generic<PEClassType>::get_ep() const -{ - return nt_headers_.OptionalHeader.AddressOfEntryPoint; -} - -//Sets image entry point -template<typename PEClassType> -void pe_properties_generic<PEClassType>::set_ep(uint32_t new_ep) -{ - nt_headers_.OptionalHeader.AddressOfEntryPoint = new_ep; -} - -//Returns file alignment -template<typename PEClassType> -uint32_t pe_properties_generic<PEClassType>::get_file_alignment() const -{ - return nt_headers_.OptionalHeader.FileAlignment; -} - -//Returns section alignment -template<typename PEClassType> -uint32_t pe_properties_generic<PEClassType>::get_section_alignment() const -{ - return nt_headers_.OptionalHeader.SectionAlignment; -} - -//Sets heap size commit for PE32 -template<typename PEClassType> -void pe_properties_generic<PEClassType>::set_heap_size_commit(uint32_t size) -{ - nt_headers_.OptionalHeader.SizeOfHeapCommit = static_cast<typename PEClassType::BaseSize>(size); -} - -//Sets heap size commit for PE32/PE64 -template<typename PEClassType> -void pe_properties_generic<PEClassType>::set_heap_size_commit(uint64_t size) -{ - nt_headers_.OptionalHeader.SizeOfHeapCommit = static_cast<typename PEClassType::BaseSize>(size); -} - -//Sets heap size reserve for PE32 -template<typename PEClassType> -void pe_properties_generic<PEClassType>::set_heap_size_reserve(uint32_t size) -{ - nt_headers_.OptionalHeader.SizeOfHeapReserve = static_cast<typename PEClassType::BaseSize>(size); -} - -//Sets heap size reserve for PE32/PE64 -template<typename PEClassType> -void pe_properties_generic<PEClassType>::set_heap_size_reserve(uint64_t size) -{ - nt_headers_.OptionalHeader.SizeOfHeapReserve = static_cast<typename PEClassType::BaseSize>(size); -} - -//Sets stack size commit for PE32 -template<typename PEClassType> -void pe_properties_generic<PEClassType>::set_stack_size_commit(uint32_t size) -{ - nt_headers_.OptionalHeader.SizeOfStackCommit = static_cast<typename PEClassType::BaseSize>(size); -} - -//Sets stack size commit for PE32/PE64 -template<typename PEClassType> -void pe_properties_generic<PEClassType>::set_stack_size_commit(uint64_t size) -{ - nt_headers_.OptionalHeader.SizeOfStackCommit = static_cast<typename PEClassType::BaseSize>(size); -} - -//Sets stack size reserve for PE32 -template<typename PEClassType> -void pe_properties_generic<PEClassType>::set_stack_size_reserve(uint32_t size) -{ - nt_headers_.OptionalHeader.SizeOfStackReserve = static_cast<typename PEClassType::BaseSize>(size); -} - -//Sets stack size reserve for PE32/PE64 -template<typename PEClassType> -void pe_properties_generic<PEClassType>::set_stack_size_reserve(uint64_t size) -{ - nt_headers_.OptionalHeader.SizeOfStackReserve = static_cast<typename PEClassType::BaseSize>(size); -} - -//Returns heap size commit for PE32 -template<typename PEClassType> -uint32_t pe_properties_generic<PEClassType>::get_heap_size_commit_32() const -{ - return static_cast<uint32_t>(nt_headers_.OptionalHeader.SizeOfHeapCommit); -} - -//Returns heap size commit for PE32/PE64 -template<typename PEClassType> -uint64_t pe_properties_generic<PEClassType>::get_heap_size_commit_64() const -{ - return static_cast<uint64_t>(nt_headers_.OptionalHeader.SizeOfHeapCommit); -} - -//Returns heap size reserve for PE32 -template<typename PEClassType> -uint32_t pe_properties_generic<PEClassType>::get_heap_size_reserve_32() const -{ - return static_cast<uint32_t>(nt_headers_.OptionalHeader.SizeOfHeapReserve); -} - -//Returns heap size reserve for PE32/PE64 -template<typename PEClassType> -uint64_t pe_properties_generic<PEClassType>::get_heap_size_reserve_64() const -{ - return static_cast<uint64_t>(nt_headers_.OptionalHeader.SizeOfHeapReserve); -} - -//Returns stack size commit for PE32 -template<typename PEClassType> -uint32_t pe_properties_generic<PEClassType>::get_stack_size_commit_32() const -{ - return static_cast<uint32_t>(nt_headers_.OptionalHeader.SizeOfStackCommit); -} - -//Returns stack size commit for PE32/PE64 -template<typename PEClassType> -uint64_t pe_properties_generic<PEClassType>::get_stack_size_commit_64() const -{ - return static_cast<uint64_t>(nt_headers_.OptionalHeader.SizeOfStackCommit); -} - -//Returns stack size reserve for PE32 -template<typename PEClassType> -uint32_t pe_properties_generic<PEClassType>::get_stack_size_reserve_32() const -{ - return static_cast<uint32_t>(nt_headers_.OptionalHeader.SizeOfStackReserve); -} - -//Returns stack size reserve for PE32/PE64 -template<typename PEClassType> -uint64_t pe_properties_generic<PEClassType>::get_stack_size_reserve_64() const -{ - return static_cast<uint64_t>(nt_headers_.OptionalHeader.SizeOfStackReserve); -} - -//Returns virtual size of image -template<typename PEClassType> -uint32_t pe_properties_generic<PEClassType>::get_size_of_image() const -{ - return nt_headers_.OptionalHeader.SizeOfImage; -} - -//Returns number of RVA and sizes (number of DATA_DIRECTORY entries) -template<typename PEClassType> -uint32_t pe_properties_generic<PEClassType>::get_number_of_rvas_and_sizes() const -{ - return nt_headers_.OptionalHeader.NumberOfRvaAndSizes; -} - -//Sets number of RVA and sizes (number of DATA_DIRECTORY entries) -template<typename PEClassType> -void pe_properties_generic<PEClassType>::set_number_of_rvas_and_sizes(uint32_t number) -{ - nt_headers_.OptionalHeader.NumberOfRvaAndSizes = number; -} - -//Returns PE characteristics -template<typename PEClassType> -uint16_t pe_properties_generic<PEClassType>::get_characteristics() const -{ - return nt_headers_.FileHeader.Characteristics; -} - -//Returns checksum of PE file from header -template<typename PEClassType> -uint32_t pe_properties_generic<PEClassType>::get_checksum() const -{ - return nt_headers_.OptionalHeader.CheckSum; -} - -//Sets checksum of PE file -template<typename PEClassType> -void pe_properties_generic<PEClassType>::set_checksum(uint32_t checksum) -{ - nt_headers_.OptionalHeader.CheckSum = checksum; -} - -//Returns DLL Characteristics -template<typename PEClassType> -uint16_t pe_properties_generic<PEClassType>::get_dll_characteristics() const -{ - return nt_headers_.OptionalHeader.DllCharacteristics; -} - -//Returns timestamp of PE file from header -template<typename PEClassType> -uint32_t pe_properties_generic<PEClassType>::get_time_date_stamp() const -{ - return nt_headers_.FileHeader.TimeDateStamp; -} - -//Sets timestamp of PE file -template<typename PEClassType> -void pe_properties_generic<PEClassType>::set_time_date_stamp(uint32_t timestamp) -{ - nt_headers_.FileHeader.TimeDateStamp = timestamp; -} - -//Sets DLL Characteristics -template<typename PEClassType> -void pe_properties_generic<PEClassType>::set_dll_characteristics(uint16_t characteristics) -{ - nt_headers_.OptionalHeader.DllCharacteristics = characteristics; -} - -//Returns Machine field value of PE file from header -template<typename PEClassType> -uint16_t pe_properties_generic<PEClassType>::get_machine() const -{ - return nt_headers_.FileHeader.Machine; -} - -//Sets Machine field value of PE file -template<typename PEClassType> -void pe_properties_generic<PEClassType>::set_machine(uint16_t machine) -{ - nt_headers_.FileHeader.Machine = machine; -} - -//Sets PE characteristics -template<typename PEClassType> -void pe_properties_generic<PEClassType>::set_characteristics(uint16_t ch) -{ - nt_headers_.FileHeader.Characteristics = ch; -} - -//Returns size of headers -template<typename PEClassType> -uint32_t pe_properties_generic<PEClassType>::get_size_of_headers() const -{ - return nt_headers_.OptionalHeader.SizeOfHeaders; -} - -//Returns subsystem -template<typename PEClassType> -uint16_t pe_properties_generic<PEClassType>::get_subsystem() const -{ - return nt_headers_.OptionalHeader.Subsystem; -} - -//Sets subsystem -template<typename PEClassType> -void pe_properties_generic<PEClassType>::set_subsystem(uint16_t subsystem) -{ - nt_headers_.OptionalHeader.Subsystem = subsystem; -} - -//Returns size of optional header -template<typename PEClassType> -uint16_t pe_properties_generic<PEClassType>::get_size_of_optional_header() const -{ - return nt_headers_.FileHeader.SizeOfOptionalHeader; -} - -//Returns PE signature -template<typename PEClassType> -uint32_t pe_properties_generic<PEClassType>::get_pe_signature() const -{ - return nt_headers_.Signature; -} - -//Returns PE magic value -template<typename PEClassType> -uint32_t pe_properties_generic<PEClassType>::get_magic() const -{ - return nt_headers_.OptionalHeader.Magic; -} - -//Sets required operation system version -template<typename PEClassType> -void pe_properties_generic<PEClassType>::set_os_version(uint16_t major, uint16_t minor) -{ - nt_headers_.OptionalHeader.MinorOperatingSystemVersion = minor; - nt_headers_.OptionalHeader.MajorOperatingSystemVersion = major; -} - -//Returns required operation system version (minor word) -template<typename PEClassType> -uint16_t pe_properties_generic<PEClassType>::get_minor_os_version() const -{ - return nt_headers_.OptionalHeader.MinorOperatingSystemVersion; -} - -//Returns required operation system version (major word) -template<typename PEClassType> -uint16_t pe_properties_generic<PEClassType>::get_major_os_version() const -{ - return nt_headers_.OptionalHeader.MajorOperatingSystemVersion; -} - -//Sets required subsystem version -template<typename PEClassType> -void pe_properties_generic<PEClassType>::set_subsystem_version(uint16_t major, uint16_t minor) -{ - nt_headers_.OptionalHeader.MinorSubsystemVersion = minor; - nt_headers_.OptionalHeader.MajorSubsystemVersion = major; -} - -//Returns required subsystem version (minor word) -template<typename PEClassType> -uint16_t pe_properties_generic<PEClassType>::get_minor_subsystem_version() const -{ - return nt_headers_.OptionalHeader.MinorSubsystemVersion; -} - -//Returns required subsystem version (major word) -template<typename PEClassType> -uint16_t pe_properties_generic<PEClassType>::get_major_subsystem_version() const -{ - return nt_headers_.OptionalHeader.MajorSubsystemVersion; -} - -//Virtual Address (VA) to Relative Virtual Address (RVA) convertions for PE32 -template<typename PEClassType> -uint32_t pe_properties_generic<PEClassType>::va_to_rva(uint32_t va, bool bound_check) const -{ - if(bound_check && static_cast<uint64_t>(va) - nt_headers_.OptionalHeader.ImageBase > pe_utils::max_dword) - throw pe_exception("Incorrect address conversion", pe_exception::incorrect_address_conversion); - - return static_cast<uint32_t>(va - nt_headers_.OptionalHeader.ImageBase); -} - -//Virtual Address (VA) to Relative Virtual Address (RVA) convertions for PE32/PE64 -template<typename PEClassType> -uint32_t pe_properties_generic<PEClassType>::va_to_rva(uint64_t va, bool bound_check) const -{ - if(bound_check && va - nt_headers_.OptionalHeader.ImageBase > pe_utils::max_dword) - throw pe_exception("Incorrect address conversion", pe_exception::incorrect_address_conversion); - - return static_cast<uint32_t>(va - nt_headers_.OptionalHeader.ImageBase); -} - -//Relative Virtual Address (RVA) to Virtual Address (VA) convertions for PE32 -template<typename PEClassType> -uint32_t pe_properties_generic<PEClassType>::rva_to_va_32(uint32_t rva) const -{ - if(!pe_utils::is_sum_safe(rva, static_cast<uint32_t>(nt_headers_.OptionalHeader.ImageBase))) - throw pe_exception("Incorrect address conversion", pe_exception::incorrect_address_conversion); - - return static_cast<uint32_t>(rva + nt_headers_.OptionalHeader.ImageBase); -} - -//Relative Virtual Address (RVA) to Virtual Address (VA) convertions for PE32/PE64 -template<typename PEClassType> -uint64_t pe_properties_generic<PEClassType>::rva_to_va_64(uint32_t rva) const -{ - return static_cast<uint64_t>(rva) + nt_headers_.OptionalHeader.ImageBase; -} - -//Returns number of sections -template<typename PEClassType> -uint16_t pe_properties_generic<PEClassType>::get_number_of_sections() const -{ - return nt_headers_.FileHeader.NumberOfSections; -} - -//Sets number of sections -template<typename PEClassType> -void pe_properties_generic<PEClassType>::set_number_of_sections(uint16_t number) -{ - nt_headers_.FileHeader.NumberOfSections = number; -} - -//Sets virtual size of image -template<typename PEClassType> -void pe_properties_generic<PEClassType>::set_size_of_image(uint32_t size) -{ - nt_headers_.OptionalHeader.SizeOfImage = size; -} - -//Sets size of headers -template<typename PEClassType> -void pe_properties_generic<PEClassType>::set_size_of_headers(uint32_t size) -{ - nt_headers_.OptionalHeader.SizeOfHeaders = size; -} - -//Sets size of optional headers -template<typename PEClassType> -void pe_properties_generic<PEClassType>::set_size_of_optional_header(uint16_t size) -{ - nt_headers_.FileHeader.SizeOfOptionalHeader = size; -} - -//Returns nt headers data pointer -template<typename PEClassType> -char* pe_properties_generic<PEClassType>::get_nt_headers_ptr() -{ - return reinterpret_cast<char*>(&nt_headers_); -} - -//Returns nt headers data pointer -template<typename PEClassType> -const char* pe_properties_generic<PEClassType>::get_nt_headers_ptr() const -{ - return reinterpret_cast<const char*>(&nt_headers_); -} - -//Returns size of NT header -template<typename PEClassType> -uint32_t pe_properties_generic<PEClassType>::get_sizeof_nt_header() const -{ - return sizeof(typename PEClassType::NtHeaders); -} - -//Returns size of optional headers -template<typename PEClassType> -uint32_t pe_properties_generic<PEClassType>::get_sizeof_opt_headers() const -{ - return sizeof(typename PEClassType::OptHeaders); -} - -//Sets file alignment (no checks) -template<typename PEClassType> -void pe_properties_generic<PEClassType>::set_file_alignment_unchecked(uint32_t alignment) -{ - nt_headers_.OptionalHeader.FileAlignment = alignment; -} - -//Sets base of code -template<typename PEClassType> -void pe_properties_generic<PEClassType>::set_base_of_code(uint32_t base) -{ - nt_headers_.OptionalHeader.BaseOfCode = base; -} - -//Returns base of code -template<typename PEClassType> -uint32_t pe_properties_generic<PEClassType>::get_base_of_code() const -{ - return nt_headers_.OptionalHeader.BaseOfCode; -} - -//Returns needed PE magic for PE or PE+ (from template parameters) -template<typename PEClassType> -uint32_t pe_properties_generic<PEClassType>::get_needed_magic() const -{ - return PEClassType::Id; -} - -//Returns PE type of this image -template<typename PEClassType> -pe_type pe_properties_generic<PEClassType>::get_pe_type() const -{ - return PEClassType::Id == image_nt_optional_hdr32_magic ? pe_type_32 : pe_type_64; -} - -//Two used instantiations for PE32 (PE) and PE64 (PE+) -template class pe_properties_generic<pe_types_class_32>; -template class pe_properties_generic<pe_types_class_64>; -} diff --git a/tools/pe_bliss/pe_properties_generic.h b/tools/pe_bliss/pe_properties_generic.h deleted file mode 100644 index 4ff906803c..0000000000 --- a/tools/pe_bliss/pe_properties_generic.h +++ /dev/null @@ -1,277 +0,0 @@ -/*************************************************************************/ -/* Copyright (c) 2015 dx, http://kaimi.ru */ -/* */ -/* Permission is hereby granted, free of charge, to any person */ -/* obtaining a copy of this software and associated documentation */ -/* files (the "Software"), to deal in the Software without */ -/* restriction, including without limitation the rights to use, */ -/* copy, modify, merge, publish, distribute, sublicense, and/or */ -/* sell copies of the Software, and to permit persons to whom the */ -/* Software is furnished to do so, subject to the following conditions: */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#include "pe_properties.h" - -namespace pe_bliss -{ -//Helper class to reduce code size and ease its editing -template< - typename NtHeadersType, - typename OptHeadersType, - uint16_t IdVal, - typename BaseSizeType, - BaseSizeType ImportSnapFlagVal, - typename TLSStructType, - typename ConfigStructType> -class pe_types -{ -public: - typedef NtHeadersType NtHeaders; //NT HEADERS type - typedef OptHeadersType OptHeaders; //NT OPTIONAL HEADER type - typedef BaseSizeType BaseSize; //Base size of different values: DWORD or ULONGLONG - typedef TLSStructType TLSStruct; //TLS structure type - typedef ConfigStructType ConfigStruct; //Configuration structure type - - static const uint16_t Id = IdVal; //Magic of PE or PE+ - static const BaseSize ImportSnapFlag = ImportSnapFlagVal; //Import snap flag value -}; - -//Portable Executable derived class for PE and PE+ -//Describes PE/PE+ dependent things -template<typename PEClassType> -class pe_properties_generic : public pe_properties -{ -public: //Constructor - virtual std::auto_ptr<pe_properties> duplicate() const; - - //Fills properly PE structures - virtual void create_pe(uint32_t section_alignment, uint16_t subsystem); - -public: - //Destructor - virtual ~pe_properties_generic(); - - -public: //DIRECTORIES - //Returns true if directory exists - virtual bool directory_exists(uint32_t id) const; - - //Removes directory - virtual void remove_directory(uint32_t id); - - //Returns directory RVA - virtual uint32_t get_directory_rva(uint32_t id) const; - //Returns directory size - virtual uint32_t get_directory_size(uint32_t id) const; - - //Sets directory RVA (just a value of PE header, no moving occurs) - virtual void set_directory_rva(uint32_t id, uint32_t rva); - //Sets directory size (just a value of PE header, no moving occurs) - virtual void set_directory_size(uint32_t id, uint32_t size); - - //Strips only zero DATA_DIRECTORY entries to count = min_count - //Returns resulting number of data directories - //strip_iat_directory - if true, even not empty IAT directory will be stripped - virtual uint32_t strip_data_directories(uint32_t min_count = 1, bool strip_iat_directory = true); - - -public: //IMAGE - //Returns PE type of this image - virtual pe_type get_pe_type() const; - - -public: //PE HEADER - //Returns image base for PE32 and PE64 respectively - virtual uint32_t get_image_base_32() const; - virtual uint64_t get_image_base_64() const; - - //Sets new image base for PE32 - virtual void set_image_base(uint32_t base); - //Sets new image base for PE32/PE+ - virtual void set_image_base_64(uint64_t base); - - //Returns image entry point - virtual uint32_t get_ep() const; - //Sets image entry point - virtual void set_ep(uint32_t new_ep); - - //Returns file alignment - virtual uint32_t get_file_alignment() const; - //Returns section alignment - virtual uint32_t get_section_alignment() const; - - //Sets heap size commit for PE32 and PE64 respectively - virtual void set_heap_size_commit(uint32_t size); - virtual void set_heap_size_commit(uint64_t size); - //Sets heap size reserve for PE32 and PE64 respectively - virtual void set_heap_size_reserve(uint32_t size); - virtual void set_heap_size_reserve(uint64_t size); - //Sets stack size commit for PE32 and PE64 respectively - virtual void set_stack_size_commit(uint32_t size); - virtual void set_stack_size_commit(uint64_t size); - //Sets stack size reserve for PE32 and PE64 respectively - virtual void set_stack_size_reserve(uint32_t size); - virtual void set_stack_size_reserve(uint64_t size); - - //Returns heap size commit for PE32 and PE64 respectively - virtual uint32_t get_heap_size_commit_32() const; - virtual uint64_t get_heap_size_commit_64() const; - //Returns heap size reserve for PE32 and PE64 respectively - virtual uint32_t get_heap_size_reserve_32() const; - virtual uint64_t get_heap_size_reserve_64() const; - //Returns stack size commit for PE32 and PE64 respectively - virtual uint32_t get_stack_size_commit_32() const; - virtual uint64_t get_stack_size_commit_64() const; - //Returns stack size reserve for PE32 and PE64 respectively - virtual uint32_t get_stack_size_reserve_32() const; - virtual uint64_t get_stack_size_reserve_64() const; - - //Returns virtual size of image - virtual uint32_t get_size_of_image() const; - - //Returns number of RVA and sizes (number of DATA_DIRECTORY entries) - virtual uint32_t get_number_of_rvas_and_sizes() const; - //Sets number of RVA and sizes (number of DATA_DIRECTORY entries) - virtual void set_number_of_rvas_and_sizes(uint32_t number); - - //Returns PE characteristics - virtual uint16_t get_characteristics() const; - //Sets PE characteristics - virtual void set_characteristics(uint16_t ch); - - //Returns size of headers - virtual uint32_t get_size_of_headers() const; - - //Returns subsystem - virtual uint16_t get_subsystem() const; - - //Sets subsystem - virtual void set_subsystem(uint16_t subsystem); - - //Returns size of optional header - virtual uint16_t get_size_of_optional_header() const; - - //Returns PE signature - virtual uint32_t get_pe_signature() const; - - //Returns PE magic value - virtual uint32_t get_magic() const; - - //Returns checksum of PE file from header - virtual uint32_t get_checksum() const; - - //Sets checksum of PE file - virtual void set_checksum(uint32_t checksum); - - //Returns timestamp of PE file from header - virtual uint32_t get_time_date_stamp() const; - - //Sets timestamp of PE file - virtual void set_time_date_stamp(uint32_t timestamp); - - //Returns Machine field value of PE file from header - virtual uint16_t get_machine() const; - - //Sets Machine field value of PE file - virtual void set_machine(uint16_t machine); - - //Returns DLL Characteristics - virtual uint16_t get_dll_characteristics() const; - - //Sets DLL Characteristics - virtual void set_dll_characteristics(uint16_t characteristics); - - //Sets required operation system version - virtual void set_os_version(uint16_t major, uint16_t minor); - - //Returns required operation system version (minor word) - virtual uint16_t get_minor_os_version() const; - - //Returns required operation system version (major word) - virtual uint16_t get_major_os_version() const; - - //Sets required subsystem version - virtual void set_subsystem_version(uint16_t major, uint16_t minor); - - //Returns required subsystem version (minor word) - virtual uint16_t get_minor_subsystem_version() const; - - //Returns required subsystem version (major word) - virtual uint16_t get_major_subsystem_version() const; - -public: //ADDRESS CONVERTIONS - //Virtual Address (VA) to Relative Virtual Address (RVA) convertions - //for PE32 and PE64 respectively - //bound_check checks integer overflow - virtual uint32_t va_to_rva(uint32_t va, bool bound_check = true) const; - virtual uint32_t va_to_rva(uint64_t va, bool bound_check = true) const; - - //Relative Virtual Address (RVA) to Virtual Address (VA) convertions - //for PE32 and PE64 respectively - virtual uint32_t rva_to_va_32(uint32_t rva) const; - virtual uint64_t rva_to_va_64(uint32_t rva) const; - - -public: //SECTIONS - //Returns number of sections - virtual uint16_t get_number_of_sections() const; - -protected: - typename PEClassType::NtHeaders nt_headers_; //NT headers (PE32 or PE64) - -public: - //Sets number of sections - virtual void set_number_of_sections(uint16_t number); - //Sets virtual size of image - virtual void set_size_of_image(uint32_t size); - //Sets size of headers - virtual void set_size_of_headers(uint32_t size); - //Sets size of optional headers - virtual void set_size_of_optional_header(uint16_t size); - //Returns nt headers data pointer - virtual char* get_nt_headers_ptr(); - //Returns nt headers data pointer - virtual const char* get_nt_headers_ptr() const; - //Returns size of NT header - virtual uint32_t get_sizeof_nt_header() const; - //Returns size of optional headers - virtual uint32_t get_sizeof_opt_headers() const; - //Sets file alignment (no checks) - virtual void set_file_alignment_unchecked(uint32_t alignment); - //Sets base of code - virtual void set_base_of_code(uint32_t base); - //Returns base of code - virtual uint32_t get_base_of_code() const; - //Returns needed PE magic for PE or PE+ (from template parameters) - virtual uint32_t get_needed_magic() const; -}; - -//Two used typedefs for PE32 (PE) and PE64 (PE+) -typedef pe_types<pe_win::image_nt_headers32, - pe_win::image_optional_header32, - pe_win::image_nt_optional_hdr32_magic, - uint32_t, - pe_win::image_ordinal_flag32, - pe_win::image_tls_directory32, - pe_win::image_load_config_directory32> pe_types_class_32; - -typedef pe_types<pe_win::image_nt_headers64, - pe_win::image_optional_header64, - pe_win::image_nt_optional_hdr64_magic, - uint64_t, - pe_win::image_ordinal_flag64, - pe_win::image_tls_directory64, - pe_win::image_load_config_directory64> pe_types_class_64; - -typedef pe_properties_generic<pe_types_class_32> pe_properties_32; -typedef pe_properties_generic<pe_types_class_64> pe_properties_64; -} diff --git a/tools/pe_bliss/pe_rebuilder.cpp b/tools/pe_bliss/pe_rebuilder.cpp deleted file mode 100644 index faf5803b8c..0000000000 --- a/tools/pe_bliss/pe_rebuilder.cpp +++ /dev/null @@ -1,214 +0,0 @@ -/*************************************************************************/ -/* Copyright (c) 2015 dx, http://kaimi.ru */ -/* */ -/* Permission is hereby granted, free of charge, to any person */ -/* obtaining a copy of this software and associated documentation */ -/* files (the "Software"), to deal in the Software without */ -/* restriction, including without limitation the rights to use, */ -/* copy, modify, merge, publish, distribute, sublicense, and/or */ -/* sell copies of the Software, and to permit persons to whom the */ -/* Software is furnished to do so, subject to the following conditions: */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#include "pe_rebuilder.h" -#include "pe_base.h" -#include "pe_structures.h" -#include "pe_exception.h" - -namespace pe_bliss -{ -using namespace pe_win; - -//Rebuilds PE image headers -//If strip_dos_header is true, DOS headers partially will be used for PE headers -//If change_size_of_headers == true, SizeOfHeaders will be recalculated automatically -//If save_bound_import == true, existing bound import directory will be saved correctly (because some compilers and bind.exe put it to PE headers) -void rebuild_pe(pe_base& pe, image_dos_header& dos_header, bool strip_dos_header, bool change_size_of_headers, bool save_bound_import) -{ - dos_header = pe.get_dos_header(); - - if(strip_dos_header) - { - //Strip stub overlay - pe.strip_stub_overlay(); - //BaseOfCode NT Headers field now overlaps - //e_lfanew field, so we're acrually setting - //e_lfanew with this call - pe.set_base_of_code(8 * sizeof(uint16_t)); - } - else - { - //Set start of PE headers - dos_header.e_lfanew = sizeof(image_dos_header) - + pe_utils::align_up(static_cast<uint32_t>(pe.get_stub_overlay().size()), sizeof(uint32_t)); - } - - section_list& sections = pe.get_image_sections(); - - //Calculate pointer to section data - size_t ptr_to_section_data = (strip_dos_header ? 8 * sizeof(uint16_t) : sizeof(image_dos_header)) + pe.get_sizeof_nt_header() - + pe_utils::align_up(pe.get_stub_overlay().size(), sizeof(uint32_t)) - - sizeof(image_data_directory) * (image_numberof_directory_entries - pe.get_number_of_rvas_and_sizes()) - + sections.size() * sizeof(image_section_header); - - if(save_bound_import && pe.has_bound_import()) - { - //It will be aligned to DWORD, because we're aligning to DWORD everything above it - pe.set_directory_rva(image_directory_entry_bound_import, static_cast<uint32_t>(ptr_to_section_data)); - ptr_to_section_data += pe.get_directory_size(image_directory_entry_bound_import); - } - - ptr_to_section_data = pe_utils::align_up(ptr_to_section_data, pe.get_file_alignment()); - - //Set size of headers and size of optional header - if(change_size_of_headers) - { - if(!pe.get_image_sections().empty()) - { - if(static_cast<uint32_t>(ptr_to_section_data) > (*sections.begin()).get_virtual_address()) - throw pe_exception("Headers of PE file are too long. Try to strip STUB or don't build bound import", pe_exception::cannot_rebuild_image); - } - - pe.set_size_of_headers(static_cast<uint32_t>(ptr_to_section_data)); - } - - //Set number of sections in PE header - pe.update_number_of_sections(); - - pe.update_image_size(); - - pe.set_size_of_optional_header(static_cast<uint16_t>(pe.get_sizeof_opt_headers() - - sizeof(image_data_directory) * (image_numberof_directory_entries - pe.get_number_of_rvas_and_sizes()))); - - //Recalculate pointer to raw data according to section list - for(section_list::iterator it = sections.begin(); it != sections.end(); ++it) - { - //Save section headers PointerToRawData - (*it).set_pointer_to_raw_data(static_cast<uint32_t>(ptr_to_section_data)); - ptr_to_section_data += (*it).get_aligned_raw_size(pe.get_file_alignment()); - } -} - -//Rebuild PE image and write it to "out" ostream -//If strip_dos_header is true, DOS headers partially will be used for PE headers -//If change_size_of_headers == true, SizeOfHeaders will be recalculated automatically -//If save_bound_import == true, existing bound import directory will be saved correctly (because some compilers and bind.exe put it to PE headers) -void rebuild_pe(pe_base& pe, std::ostream& out, bool strip_dos_header, bool change_size_of_headers, bool save_bound_import) -{ - if(out.bad()) - throw pe_exception("Stream is bad", pe_exception::stream_is_bad); - - if(save_bound_import && pe.has_bound_import()) - { - if(pe.section_data_length_from_rva(pe.get_directory_rva(image_directory_entry_bound_import), pe.get_directory_rva(image_directory_entry_bound_import), section_data_raw, true) - < pe.get_directory_size(image_directory_entry_bound_import)) - throw pe_exception("Incorrect bound import directory", pe_exception::incorrect_bound_import_directory); - } - - //Change ostream state - out.exceptions(std::ios::goodbit); - out.clear(); - - uint32_t original_bound_import_rva = pe.has_bound_import() ? pe.get_directory_rva(image_directory_entry_bound_import) : 0; - if(original_bound_import_rva && original_bound_import_rva > pe.get_size_of_headers()) - { - //No need to do anything with bound import directory - //if it is placed inside of any section, not headers - original_bound_import_rva = 0; - save_bound_import = false; - } - - { - image_dos_header dos_header; - - //Rebuild PE image headers - rebuild_pe(pe, dos_header, strip_dos_header, change_size_of_headers, save_bound_import); - - //Write DOS header - out.write(reinterpret_cast<const char*>(&dos_header), strip_dos_header ? 8 * sizeof(uint16_t) : sizeof(image_dos_header)); - } - - //If we have stub overlay, write it too - { - const std::string& stub = pe.get_stub_overlay(); - if(stub.size()) - { - out.write(stub.data(), stub.size()); - size_t aligned_size = pe_utils::align_up(stub.size(), sizeof(uint32_t)); - //Align PE header, which is right after rich overlay - while(aligned_size > stub.size()) - { - out.put('\0'); - --aligned_size; - } - } - } - - //Write NT headers - out.write(static_cast<const pe_base&>(pe).get_nt_headers_ptr(), pe.get_sizeof_nt_header() - - sizeof(image_data_directory) * (image_numberof_directory_entries - pe.get_number_of_rvas_and_sizes())); - - //Write section headers - const section_list& sections = pe.get_image_sections(); - for(section_list::const_iterator it = sections.begin(); it != sections.end(); ++it) - { - if(it == sections.end() - 1) //If last section encountered - { - image_section_header header((*it).get_raw_header()); - header.SizeOfRawData = static_cast<uint32_t>((*it).get_raw_data().length()); //Set non-aligned actual data length for it - out.write(reinterpret_cast<const char*>(&header), sizeof(image_section_header)); - } - else - { - out.write(reinterpret_cast<const char*>(&(*it).get_raw_header()), sizeof(image_section_header)); - } - } - - //Write bound import data if requested - if(save_bound_import && pe.has_bound_import()) - { - out.write(pe.section_data_from_rva(original_bound_import_rva, section_data_raw, true), - pe.get_directory_size(image_directory_entry_bound_import)); - } - - //Write section data finally - for(section_list::const_iterator it = sections.begin(); it != sections.end(); ++it) - { - const section& s = *it; - - std::streamoff wpos = out.tellp(); - - //Fill unused overlay data between sections with null bytes - for(unsigned int i = 0; i < s.get_pointer_to_raw_data() - wpos; i++) - out.put(0); - - //Write raw section data - out.write(s.get_raw_data().data(), s.get_raw_data().length()); - } -} - -//Rebuild PE image and write it to "out" file -//If strip_dos_header is true, DOS headers partially will be used for PE headers -//If change_size_of_headers == true, SizeOfHeaders will be recalculated automatically -//If save_bound_import == true, existing bound import directory will be saved correctly (because some compilers and bind.exe put it to PE headers) -void rebuild_pe(pe_base& pe, const char* out, bool strip_dos_header, bool change_size_of_headers, bool save_bound_import) -{ - std::ofstream pe_file(out, std::ios::out | std::ios::binary | std::ios::trunc); - if(!pe_file) - { - throw pe_exception("Error in open file.", pe_exception::stream_is_bad); - } - rebuild_pe(pe, pe_file, strip_dos_header, change_size_of_headers, save_bound_import); -} - - -} diff --git a/tools/pe_bliss/pe_rebuilder.h b/tools/pe_bliss/pe_rebuilder.h deleted file mode 100644 index 319807e5c9..0000000000 --- a/tools/pe_bliss/pe_rebuilder.h +++ /dev/null @@ -1,40 +0,0 @@ -/*************************************************************************/ -/* Copyright (c) 2015 dx, http://kaimi.ru */ -/* */ -/* Permission is hereby granted, free of charge, to any person */ -/* obtaining a copy of this software and associated documentation */ -/* files (the "Software"), to deal in the Software without */ -/* restriction, including without limitation the rights to use, */ -/* copy, modify, merge, publish, distribute, sublicense, and/or */ -/* sell copies of the Software, and to permit persons to whom the */ -/* Software is furnished to do so, subject to the following conditions: */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#pragma once -#include <ostream> -#include <fstream> - -namespace pe_bliss -{ -class pe_base; -//Rebuilds PE image, writes resulting image to ostream "out". If strip_dos_header == true, DOS header will be stripped a little -//If change_size_of_headers == true, SizeOfHeaders will be recalculated automatically -//If save_bound_import == true, existing bound import directory will be saved correctly (because some compilers and bind.exe put it to PE headers) -void rebuild_pe(pe_base& pe, std::ostream& out, bool strip_dos_header = false, bool change_size_of_headers = true, bool save_bound_import = true); - -//Rebuild PE image and write it to "out" file -//If strip_dos_header is true, DOS headers partially will be used for PE headers -//If change_size_of_headers == true, SizeOfHeaders will be recalculated automatically -//If save_bound_import == true, existing bound import directory will be saved correctly (because some compilers and bind.exe put it to PE headers) -void rebuild_pe(pe_base& pe, const char* out, bool strip_dos_header = false, bool change_size_of_headers = true, bool save_bound_import = true); - -} diff --git a/tools/pe_bliss/pe_relocations.cpp b/tools/pe_bliss/pe_relocations.cpp deleted file mode 100644 index d5357dd219..0000000000 --- a/tools/pe_bliss/pe_relocations.cpp +++ /dev/null @@ -1,320 +0,0 @@ -/*************************************************************************/ -/* Copyright (c) 2015 dx, http://kaimi.ru */ -/* */ -/* Permission is hereby granted, free of charge, to any person */ -/* obtaining a copy of this software and associated documentation */ -/* files (the "Software"), to deal in the Software without */ -/* restriction, including without limitation the rights to use, */ -/* copy, modify, merge, publish, distribute, sublicense, and/or */ -/* sell copies of the Software, and to permit persons to whom the */ -/* Software is furnished to do so, subject to the following conditions: */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#include <string.h> -#include "pe_relocations.h" -#include "pe_properties_generic.h" - -namespace pe_bliss -{ -using namespace pe_win; - -//RELOCATIONS -//Default constructor -relocation_entry::relocation_entry() - :rva_(0), type_(0) -{} - -//Constructor from relocation item (WORD) -relocation_entry::relocation_entry(uint16_t relocation_value) - :rva_(relocation_value & ((1 << 12) - 1)), type_(relocation_value >> 12) -{} - -//Constructor from relative rva and relocation type -relocation_entry::relocation_entry(uint16_t rrva, uint16_t type) - :rva_(rrva), type_(type) -{} - -//Returns RVA of relocation -uint16_t relocation_entry::get_rva() const -{ - return rva_; -} - -//Returns type of relocation -uint16_t relocation_entry::get_type() const -{ - return type_; -} - -//Sets RVA of relocation -void relocation_entry::set_rva(uint16_t rva) -{ - rva_ = rva; -} - -//Sets type of relocation -void relocation_entry::set_type(uint16_t type) -{ - type_ = type; -} - -//Returns relocation item (rrva + type) -uint16_t relocation_entry::get_item() const -{ - return rva_ | (type_ << 12); -} - -//Sets relocation item (rrva + type) -void relocation_entry::set_item(uint16_t item) -{ - rva_ = item & ((1 << 12) - 1); - type_ = item >> 12; -} - -//Returns relocation list -const relocation_table::relocation_list& relocation_table::get_relocations() const -{ - return relocations_; -} - -//Adds relocation to table -void relocation_table::add_relocation(const relocation_entry& entry) -{ - relocations_.push_back(entry); -} - -//Default constructor -relocation_table::relocation_table() - :rva_(0) -{} - -//Constructor from RVA of relocation table -relocation_table::relocation_table(uint32_t rva) - :rva_(rva) -{} - -//Returns RVA of block -uint32_t relocation_table::get_rva() const -{ - return rva_; -} - -//Sets RVA of block -void relocation_table::set_rva(uint32_t rva) -{ - rva_ = rva; -} - -//Returns changeable relocation list -relocation_table::relocation_list& relocation_table::get_relocations() -{ - return relocations_; -} - -//Get relocation list of pe file, supports one-word sized relocations only -//If list_absolute_entries = true, IMAGE_REL_BASED_ABSOLUTE will be listed -const relocation_table_list get_relocations(const pe_base& pe, bool list_absolute_entries) -{ - relocation_table_list ret; - - //If image does not have relocations - if(!pe.has_reloc()) - return ret; - - //Check the length in bytes of the section containing relocation directory - if(pe.section_data_length_from_rva(pe.get_directory_rva(image_directory_entry_basereloc), - pe.get_directory_rva(image_directory_entry_basereloc), section_data_virtual, true) - < sizeof(image_base_relocation)) - throw pe_exception("Incorrect relocation directory", pe_exception::incorrect_relocation_directory); - - unsigned long current_pos = pe.get_directory_rva(image_directory_entry_basereloc); - //First IMAGE_BASE_RELOCATION table - image_base_relocation reloc_table = pe.section_data_from_rva<image_base_relocation>(current_pos, section_data_virtual, true); - - if(reloc_table.SizeOfBlock % 2) - throw pe_exception("Incorrect relocation directory", pe_exception::incorrect_relocation_directory); - - unsigned long reloc_size = pe.get_directory_size(image_directory_entry_basereloc); - unsigned long read_size = 0; - - //reloc_table.VirtualAddress is not checked (not so important) - while(reloc_table.SizeOfBlock && read_size < reloc_size) - { - //Create relocation table - relocation_table table; - //Save RVA - table.set_rva(reloc_table.VirtualAddress); - - if(!pe_utils::is_sum_safe(current_pos, reloc_table.SizeOfBlock)) - throw pe_exception("Incorrect relocation directory", pe_exception::incorrect_relocation_directory); - - //List all relocations - for(unsigned long i = sizeof(image_base_relocation); i < reloc_table.SizeOfBlock; i += sizeof(uint16_t)) - { - relocation_entry entry(pe.section_data_from_rva<uint16_t>(current_pos + i, section_data_virtual, true)); - if(list_absolute_entries || entry.get_type() != image_rel_based_absolute) - table.add_relocation(entry); - } - - //Save table - ret.push_back(table); - - //Go to next relocation block - if(!pe_utils::is_sum_safe(current_pos, reloc_table.SizeOfBlock)) - throw pe_exception("Incorrect relocation directory", pe_exception::incorrect_relocation_directory); - - current_pos += reloc_table.SizeOfBlock; - read_size += reloc_table.SizeOfBlock; - reloc_table = pe.section_data_from_rva<image_base_relocation>(current_pos, section_data_virtual, true); - } - - return ret; -} - -//Simple relocations rebuilder -//To keep PE file working, don't remove any of existing relocations in -//relocation_table_list returned by a call to get_relocations() function -//auto_strip_last_section - if true and relocations are placed in the last section, it will be automatically stripped -//offset_from_section_start - offset from the beginning of reloc_section, where relocations data will be situated -//If save_to_pe_header is true, PE header will be modified automatically -const image_directory rebuild_relocations(pe_base& pe, const relocation_table_list& relocs, section& reloc_section, uint32_t offset_from_section_start, bool save_to_pe_header, bool auto_strip_last_section) -{ - //Check that reloc_section is attached to this PE image - if(!pe.section_attached(reloc_section)) - throw pe_exception("Relocations section must be attached to PE file", pe_exception::section_is_not_attached); - - uint32_t current_reloc_data_pos = pe_utils::align_up(offset_from_section_start, sizeof(uint32_t)); - - uint32_t needed_size = current_reloc_data_pos - offset_from_section_start; //Calculate needed size for relocation tables - uint32_t size_delta = needed_size; - - uint32_t start_reloc_pos = current_reloc_data_pos; - - //Enumerate relocation tables - for(relocation_table_list::const_iterator it = relocs.begin(); it != relocs.end(); ++it) - { - needed_size += static_cast<uint32_t>((*it).get_relocations().size() * sizeof(uint16_t) /* relocations */ + sizeof(image_base_relocation) /* table header */); - //End of each table will be DWORD-aligned - if((start_reloc_pos + needed_size - size_delta) % sizeof(uint32_t)) - needed_size += sizeof(uint16_t); //Align it with IMAGE_REL_BASED_ABSOLUTE relocation - } - - //Check if reloc_section is last one. If it's not, check if there's enough place for relocations data - if(&reloc_section != &*(pe.get_image_sections().end() - 1) && - (reloc_section.empty() || pe_utils::align_up(reloc_section.get_size_of_raw_data(), pe.get_file_alignment()) < needed_size + current_reloc_data_pos)) - throw pe_exception("Insufficient space for relocations directory", pe_exception::insufficient_space); - - std::string& raw_data = reloc_section.get_raw_data(); - - //This will be done only if reloc_section is the last section of image or for section with unaligned raw length of data - if(raw_data.length() < needed_size + current_reloc_data_pos) - raw_data.resize(needed_size + current_reloc_data_pos); //Expand section raw data - - //Enumerate relocation tables - for(relocation_table_list::const_iterator it = relocs.begin(); it != relocs.end(); ++it) - { - //Create relocation table header - image_base_relocation reloc; - reloc.VirtualAddress = (*it).get_rva(); - const relocation_table::relocation_list& reloc_list = (*it).get_relocations(); - reloc.SizeOfBlock = static_cast<uint32_t>(sizeof(image_base_relocation) + sizeof(uint16_t) * reloc_list.size()); - if((reloc_list.size() * sizeof(uint16_t)) % sizeof(uint32_t)) //If we must align end of relocation table - reloc.SizeOfBlock += sizeof(uint16_t); - - memcpy(&raw_data[current_reloc_data_pos], &reloc, sizeof(reloc)); - current_reloc_data_pos += sizeof(reloc); - - //Enumerate relocations in table - for(relocation_table::relocation_list::const_iterator r = reloc_list.begin(); r != reloc_list.end(); ++r) - { - //Save relocations - uint16_t reloc_value = (*r).get_item(); - memcpy(&raw_data[current_reloc_data_pos], &reloc_value, sizeof(reloc_value)); - current_reloc_data_pos += sizeof(reloc_value); - } - - if(current_reloc_data_pos % sizeof(uint32_t)) //If end of table is not DWORD-aligned - { - memset(&raw_data[current_reloc_data_pos], 0, sizeof(uint16_t)); //Align it with IMAGE_REL_BASED_ABSOLUTE relocation - current_reloc_data_pos += sizeof(uint16_t); - } - } - - image_directory ret(pe.rva_from_section_offset(reloc_section, start_reloc_pos), needed_size - size_delta); - - //Adjust section raw and virtual sizes - pe.recalculate_section_sizes(reloc_section, auto_strip_last_section); - - //If auto-rewrite of PE headers is required - if(save_to_pe_header) - { - pe.set_directory_rva(image_directory_entry_basereloc, ret.get_rva()); - pe.set_directory_size(image_directory_entry_basereloc, ret.get_size()); - - pe.clear_characteristics_flags(image_file_relocs_stripped); - pe.set_dll_characteristics(pe.get_dll_characteristics() | image_dllcharacteristics_dynamic_base); - } - - return ret; -} - -//Recalculates image base with the help of relocation tables -void rebase_image(pe_base& pe, const relocation_table_list& tables, uint64_t new_base) -{ - pe.get_pe_type() == pe_type_32 - ? rebase_image_base<pe_types_class_32>(pe, tables, new_base) - : rebase_image_base<pe_types_class_64>(pe, tables, new_base); -} - -//RELOCATIONS -//Recalculates image base with the help of relocation tables -//Recalculates VAs of DWORDS/QWORDS in image according to relocations -//Notice: if you move some critical structures like TLS, image relocations will not fix new -//positions of TLS VAs. Instead, some bytes that now doesn't belong to TLS will be fixed. -//It is recommended to rebase image in the very beginning and move all structures afterwards. -template<typename PEClassType> -void rebase_image_base(pe_base& pe, const relocation_table_list& tables, uint64_t new_base) -{ - //Get current image base value - typename PEClassType::BaseSize image_base; - pe.get_image_base(image_base); - - //ImageBase difference - typename PEClassType::BaseSize base_rel = static_cast<typename PEClassType::BaseSize>(static_cast<int64_t>(new_base) - image_base); - - //We need to fix addresses from relocation tables - //Enumerate relocation tables - for(relocation_table_list::const_iterator it = tables.begin(); it != tables.end(); ++it) - { - const relocation_table::relocation_list& relocs = (*it).get_relocations(); - - uint32_t base_rva = (*it).get_rva(); - - //Enumerate relocations - for(relocation_table::relocation_list::const_iterator rel = relocs.begin(); rel != relocs.end(); ++rel) - { - //Skip ABSOLUTE entries - if((*rel).get_type() == pe_win::image_rel_based_absolute) - continue; - - //Recalculate value by RVA and rewrite it - uint32_t current_rva = base_rva + (*rel).get_rva(); - typename PEClassType::BaseSize value = pe.section_data_from_rva<typename PEClassType::BaseSize>(current_rva, section_data_raw, true); - value += base_rel; - memcpy(pe.section_data_from_rva(current_rva, true), &value, sizeof(value)); - } - } - - //Finally, save new image base - pe.set_image_base_64(new_base); -} -} diff --git a/tools/pe_bliss/pe_relocations.h b/tools/pe_bliss/pe_relocations.h deleted file mode 100644 index 1bc8b2a405..0000000000 --- a/tools/pe_bliss/pe_relocations.h +++ /dev/null @@ -1,122 +0,0 @@ -/*************************************************************************/ -/* Copyright (c) 2015 dx, http://kaimi.ru */ -/* */ -/* Permission is hereby granted, free of charge, to any person */ -/* obtaining a copy of this software and associated documentation */ -/* files (the "Software"), to deal in the Software without */ -/* restriction, including without limitation the rights to use, */ -/* copy, modify, merge, publish, distribute, sublicense, and/or */ -/* sell copies of the Software, and to permit persons to whom the */ -/* Software is furnished to do so, subject to the following conditions: */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#pragma once -#include <vector> -#include "pe_structures.h" -#include "pe_base.h" -#include "pe_directory.h" - -namespace pe_bliss -{ -//Class representing relocation entry -//RVA of relocation is not actually RVA, but -//(real RVA) - (RVA of table) -class relocation_entry -{ -public: - //Default constructor - relocation_entry(); - //Constructor from relocation item (WORD) - explicit relocation_entry(uint16_t relocation_value); - //Constructor from relative rva and relocation type - relocation_entry(uint16_t rrva, uint16_t type); - - //Returns RVA of relocation (actually, relative RVA from relocation table RVA) - uint16_t get_rva() const; - //Returns type of relocation - uint16_t get_type() const; - - //Returns relocation item (rrva + type) - uint16_t get_item() const; - -public: //Setters do not change everything inside image, they are used by PE class - //You can also use them to rebuild relocations using rebuild_relocations() - - //Sets RVA of relocation (actually, relative RVA from relocation table RVA) - void set_rva(uint16_t rva); - //Sets type of relocation - void set_type(uint16_t type); - - //Sets relocation item (rrva + type) - void set_item(uint16_t item); - -private: - uint16_t rva_; - uint16_t type_; -}; - -//Class representing relocation table -class relocation_table -{ -public: - typedef std::vector<relocation_entry> relocation_list; - -public: - //Default constructor - relocation_table(); - //Constructor from RVA of relocation table - explicit relocation_table(uint32_t rva); - - //Returns relocation list - const relocation_list& get_relocations() const; - //Returns RVA of block - uint32_t get_rva() const; - -public: //These functions do not change everything inside image, they are used by PE class - //You can also use them to rebuild relocations using rebuild_relocations() - - //Adds relocation to table - void add_relocation(const relocation_entry& entry); - //Returns changeable relocation list - relocation_list& get_relocations(); - //Sets RVA of block - void set_rva(uint32_t rva); - -private: - uint32_t rva_; - relocation_list relocations_; -}; - -typedef std::vector<relocation_table> relocation_table_list; - -//Get relocation list of pe file, supports one-word sized relocations only -//If list_absolute_entries = true, IMAGE_REL_BASED_ABSOLUTE will be listed -const relocation_table_list get_relocations(const pe_base& pe, bool list_absolute_entries = false); - -//Simple relocations rebuilder -//To keep PE file working, don't remove any of existing relocations in -//relocation_table_list returned by a call to get_relocations() function -//auto_strip_last_section - if true and relocations are placed in the last section, it will be automatically stripped -//offset_from_section_start - offset from the beginning of reloc_section, where relocations data will be situated -//If save_to_pe_header is true, PE header will be modified automatically -const image_directory rebuild_relocations(pe_base& pe, const relocation_table_list& relocs, section& reloc_section, uint32_t offset_from_section_start = 0, bool save_to_pe_header = true, bool auto_strip_last_section = true); - -//Recalculates image base with the help of relocation tables -//Recalculates VAs of DWORDS/QWORDS in image according to relocations -//Notice: if you move some critical structures like TLS, image relocations will not fix new -//positions of TLS VAs. Instead, some bytes that now doesn't belong to TLS will be fixed. -//It is recommended to rebase image in the very beginning and move all structures afterwards. -void rebase_image(pe_base& pe, const relocation_table_list& tables, uint64_t new_base); - -template<typename PEClassType> -void rebase_image_base(pe_base& pe, const relocation_table_list& tables, uint64_t new_base); -} diff --git a/tools/pe_bliss/pe_resource_manager.cpp b/tools/pe_bliss/pe_resource_manager.cpp deleted file mode 100644 index 0ee7840ff0..0000000000 --- a/tools/pe_bliss/pe_resource_manager.cpp +++ /dev/null @@ -1,286 +0,0 @@ -/*************************************************************************/ -/* Copyright (c) 2015 dx, http://kaimi.ru */ -/* */ -/* Permission is hereby granted, free of charge, to any person */ -/* obtaining a copy of this software and associated documentation */ -/* files (the "Software"), to deal in the Software without */ -/* restriction, including without limitation the rights to use, */ -/* copy, modify, merge, publish, distribute, sublicense, and/or */ -/* sell copies of the Software, and to permit persons to whom the */ -/* Software is furnished to do so, subject to the following conditions: */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#include <algorithm> -#include <sstream> -#include <iomanip> -#include <math.h> -#include <string.h> -#include "pe_resource_manager.h" -#include "resource_internal.h" - -namespace pe_bliss -{ -using namespace pe_win; - -//Constructor from root resource directory -pe_resource_manager::pe_resource_manager(resource_directory& root_directory) - :pe_resource_viewer(root_directory), root_dir_edit_(root_directory) -{} - -resource_directory& pe_resource_manager::get_root_directory() -{ - return root_dir_edit_; -} - -//Removes all resources of given type or root name -//If there's more than one directory entry of a given type, only the -//first one will be deleted (that's an unusual situation) -//Returns true if resource was deleted -bool pe_resource_manager::remove_resource_type(resource_type type) -{ - //Search for resource type - resource_directory::entry_list& entries = root_dir_edit_.get_entry_list(); - resource_directory::entry_list::iterator it = std::find_if(entries.begin(), entries.end(), resource_directory::id_entry_finder(type)); - if(it != entries.end()) - { - //Remove it, if found - entries.erase(it); - return true; - } - - return false; -} - -bool pe_resource_manager::remove_resource(const std::wstring& root_name) -{ - //Search for resource type - resource_directory::entry_list& entries = root_dir_edit_.get_entry_list(); - resource_directory::entry_list::iterator it = std::find_if(entries.begin(), entries.end(), resource_directory::name_entry_finder(root_name)); - if(it != entries.end()) - { - //Remove it, if found - entries.erase(it); - return true; - } - - return false; -} - -//Helper to remove resource -bool pe_resource_manager::remove_resource(const resource_directory::entry_finder& root_finder, const resource_directory::entry_finder& finder) -{ - //Search for resource type - resource_directory::entry_list& entries_type = root_dir_edit_.get_entry_list(); - resource_directory::entry_list::iterator it_type = std::find_if(entries_type.begin(), entries_type.end(), root_finder); - if(it_type != entries_type.end()) - { - //Search for resource name/ID with "finder" - resource_directory::entry_list& entries_name = (*it_type).get_resource_directory().get_entry_list(); - resource_directory::entry_list::iterator it_name = std::find_if(entries_name.begin(), entries_name.end(), finder); - if(it_name != entries_name.end()) - { - //Erase resource, if found - entries_name.erase(it_name); - if(entries_name.empty()) - entries_type.erase(it_type); - - return true; - } - } - - return false; -} - -//Removes all resource languages by resource type/root name and name -//Deletes only one entry of given type and name -//Returns true if resource was deleted -bool pe_resource_manager::remove_resource(resource_type type, const std::wstring& name) -{ - return remove_resource(resource_directory::entry_finder(type), resource_directory::entry_finder(name)); -} - -bool pe_resource_manager::remove_resource(const std::wstring& root_name, const std::wstring& name) -{ - return remove_resource(resource_directory::entry_finder(root_name), resource_directory::entry_finder(name)); -} - -//Removes all resource languages by resource type/root name and ID -//Deletes only one entry of given type and ID -//Returns true if resource was deleted -bool pe_resource_manager::remove_resource(resource_type type, uint32_t id) -{ - return remove_resource(resource_directory::entry_finder(type), resource_directory::entry_finder(id)); -} - -bool pe_resource_manager::remove_resource(const std::wstring& root_name, uint32_t id) -{ - return remove_resource(resource_directory::entry_finder(root_name), resource_directory::entry_finder(id)); -} - -//Helper to remove resource -bool pe_resource_manager::remove_resource(const resource_directory::entry_finder& root_finder, const resource_directory::entry_finder& finder, uint32_t language) -{ - //Search for resource type - resource_directory::entry_list& entries_type = root_dir_edit_.get_entry_list(); - resource_directory::entry_list::iterator it_type = std::find_if(entries_type.begin(), entries_type.end(), root_finder); - if(it_type != entries_type.end()) - { - //Search for resource name/ID with "finder" - resource_directory::entry_list& entries_name = (*it_type).get_resource_directory().get_entry_list(); - resource_directory::entry_list::iterator it_name = std::find_if(entries_name.begin(), entries_name.end(), finder); - if(it_name != entries_name.end()) - { - //Search for resource language - resource_directory::entry_list& entries_lang = (*it_name).get_resource_directory().get_entry_list(); - resource_directory::entry_list::iterator it_lang = std::find_if(entries_lang.begin(), entries_lang.end(), resource_directory::id_entry_finder(language)); - if(it_lang != entries_lang.end()) - { - //Erase resource, if found - entries_lang.erase(it_lang); - if(entries_lang.empty()) - { - entries_name.erase(it_name); - if(entries_name.empty()) - entries_type.erase(it_type); - } - - return true; - } - } - } - - return false; -} - -//Removes resource language by resource type/root name and name -//Deletes only one entry of given type, name and language -//Returns true if resource was deleted -bool pe_resource_manager::remove_resource(resource_type type, const std::wstring& name, uint32_t language) -{ - return remove_resource(resource_directory::entry_finder(type), resource_directory::entry_finder(name), language); -} - -bool pe_resource_manager::remove_resource(const std::wstring& root_name, const std::wstring& name, uint32_t language) -{ - return remove_resource(resource_directory::entry_finder(root_name), resource_directory::entry_finder(name), language); -} - -//Removes recource language by resource type/root name and ID -//Deletes only one entry of given type, ID and language -//Returns true if resource was deleted -bool pe_resource_manager::remove_resource(resource_type type, uint32_t id, uint32_t language) -{ - return remove_resource(resource_directory::entry_finder(type), resource_directory::entry_finder(id), language); -} - -bool pe_resource_manager::remove_resource(const std::wstring& root_name, uint32_t id, uint32_t language) -{ - return remove_resource(resource_directory::entry_finder(root_name), resource_directory::entry_finder(id), language); -} - -//Helper to add/replace resource -void pe_resource_manager::add_resource(const std::string& data, resource_type type, resource_directory_entry& new_entry, const resource_directory::entry_finder& finder, uint32_t language, uint32_t codepage, uint32_t timestamp) -{ - resource_directory_entry new_type_entry; - new_type_entry.set_id(type); - - add_resource(data, new_type_entry, resource_directory::entry_finder(type), new_entry, finder, language, codepage, timestamp); -} - -//Helper to add/replace resource -void pe_resource_manager::add_resource(const std::string& data, const std::wstring& root_name, resource_directory_entry& new_entry, const resource_directory::entry_finder& finder, uint32_t language, uint32_t codepage, uint32_t timestamp) -{ - resource_directory_entry new_type_entry; - new_type_entry.set_name(root_name); - - add_resource(data, new_type_entry, resource_directory::entry_finder(root_name), new_entry, finder, language, codepage, timestamp); -} - -//Helper to add/replace resource -void pe_resource_manager::add_resource(const std::string& data, resource_directory_entry& new_root_entry, const resource_directory::entry_finder& root_finder, resource_directory_entry& new_entry, const resource_directory::entry_finder& finder, uint32_t language, uint32_t codepage, uint32_t timestamp) -{ - //Search for resource type - resource_directory::entry_list* entries = &root_dir_edit_.get_entry_list(); - resource_directory::entry_list::iterator it = std::find_if(entries->begin(), entries->end(), root_finder); - if(it == entries->end()) - { - //Add resource type directory, if it was not found - resource_directory dir; - dir.set_timestamp(timestamp); - new_root_entry.add_resource_directory(dir); - entries->push_back(new_root_entry); - it = entries->end() - 1; - } - - //Search for resource name/ID directory with "finder" - entries = &(*it).get_resource_directory().get_entry_list(); - it = std::find_if(entries->begin(), entries->end(), finder); - if(it == entries->end()) - { - //Add resource name/ID directory, if it was not found - resource_directory dir; - dir.set_timestamp(timestamp); - new_entry.add_resource_directory(dir); - entries->push_back(new_entry); - it = entries->end() - 1; - } - - //Search for data resource entry by language - entries = &(*it).get_resource_directory().get_entry_list(); - it = std::find_if(entries->begin(), entries->end(), resource_directory::id_entry_finder(language)); - if(it != entries->end()) - entries->erase(it); //Erase it, if found - - //Add new data entry - resource_directory_entry new_dir_data_entry; - resource_data_entry data_dir(data, codepage); - new_dir_data_entry.add_data_entry(data_dir); - new_dir_data_entry.set_id(language); - entries->push_back(new_dir_data_entry); -} - -//Adds resource. If resource already exists, replaces it -void pe_resource_manager::add_resource(const std::string& data, resource_type type, const std::wstring& name, uint32_t language, uint32_t codepage, uint32_t timestamp) -{ - resource_directory_entry new_entry; - new_entry.set_name(name); - - add_resource(data, type, new_entry, resource_directory::entry_finder(name), language, codepage, timestamp); -} - -//Adds resource. If resource already exists, replaces it -void pe_resource_manager::add_resource(const std::string& data, const std::wstring& root_name, const std::wstring& name, uint32_t language, uint32_t codepage, uint32_t timestamp) -{ - resource_directory_entry new_entry; - new_entry.set_name(name); - - add_resource(data, root_name, new_entry, resource_directory::entry_finder(name), language, codepage, timestamp); -} - -//Adds resource. If resource already exists, replaces it -void pe_resource_manager::add_resource(const std::string& data, resource_type type, uint32_t id, uint32_t language, uint32_t codepage, uint32_t timestamp) -{ - resource_directory_entry new_entry; - new_entry.set_id(id); - - add_resource(data, type, new_entry, resource_directory::entry_finder(id), language, codepage, timestamp); -} - -//Adds resource. If resource already exists, replaces it -void pe_resource_manager::add_resource(const std::string& data, const std::wstring& root_name, uint32_t id, uint32_t language, uint32_t codepage, uint32_t timestamp) -{ - resource_directory_entry new_entry; - new_entry.set_id(id); - - add_resource(data, root_name, new_entry, resource_directory::entry_finder(id), language, codepage, timestamp); -} -} diff --git a/tools/pe_bliss/pe_resource_manager.h b/tools/pe_bliss/pe_resource_manager.h deleted file mode 100644 index 85d7f44a8a..0000000000 --- a/tools/pe_bliss/pe_resource_manager.h +++ /dev/null @@ -1,113 +0,0 @@ -/*************************************************************************/ -/* Copyright (c) 2015 dx, http://kaimi.ru */ -/* */ -/* Permission is hereby granted, free of charge, to any person */ -/* obtaining a copy of this software and associated documentation */ -/* files (the "Software"), to deal in the Software without */ -/* restriction, including without limitation the rights to use, */ -/* copy, modify, merge, publish, distribute, sublicense, and/or */ -/* sell copies of the Software, and to permit persons to whom the */ -/* Software is furnished to do so, subject to the following conditions: */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#pragma once -#include <map> -#include <sstream> -#include <string> -#include <memory> -#include "pe_base.h" -#include "pe_structures.h" -#include "pe_resources.h" -#include "message_table.h" -#include "file_version_info.h" -#include "pe_resource_viewer.h" -#include "resource_data_info.h" - -namespace pe_bliss -{ -//Derived class to edit PE resources -class pe_resource_manager : public pe_resource_viewer -{ -public: - //Constructor from root resource directory - explicit pe_resource_manager(resource_directory& root_directory); - - resource_directory& get_root_directory(); - -public: //Resource editing - //Removes all resources of given type or root name - //If there's more than one directory entry of a given type, only the - //first one will be deleted (that's an unusual situation) - //Returns true if resource was deleted - bool remove_resource_type(resource_type type); - bool remove_resource(const std::wstring& root_name); - - //Removes all resource languages by resource type/root name and name - //Deletes only one entry of given type and name - //Returns true if resource was deleted - bool remove_resource(resource_type type, const std::wstring& name); - bool remove_resource(const std::wstring& root_name, const std::wstring& name); - //Removes all resource languages by resource type/root name and ID - //Deletes only one entry of given type and ID - //Returns true if resource was deleted - bool remove_resource(resource_type type, uint32_t id); - bool remove_resource(const std::wstring& root_name, uint32_t id); - - //Removes resource language by resource type/root name and name - //Deletes only one entry of given type, name and language - //Returns true if resource was deleted - bool remove_resource(resource_type type, const std::wstring& name, uint32_t language); - bool remove_resource(const std::wstring& root_name, const std::wstring& name, uint32_t language); - //Removes recource language by resource type/root name and ID - //Deletes only one entry of given type, ID and language - //Returns true if resource was deleted - bool remove_resource(resource_type type, uint32_t id, uint32_t language); - bool remove_resource(const std::wstring& root_name, uint32_t id, uint32_t language); - - //Adds resource. If resource already exists, replaces it - //timestamp will be used for directories that will be added - void add_resource(const std::string& data, resource_type type, const std::wstring& name, uint32_t language, uint32_t codepage = 0, uint32_t timestamp = 0); - void add_resource(const std::string& data, const std::wstring& root_name, const std::wstring& name, uint32_t language, uint32_t codepage = 0, uint32_t timestamp = 0); - //Adds resource. If resource already exists, replaces it - //timestamp will be used for directories that will be added - void add_resource(const std::string& data, resource_type type, uint32_t id, uint32_t language, uint32_t codepage = 0, uint32_t timestamp = 0); - void add_resource(const std::string& data, const std::wstring& root_name, uint32_t id, uint32_t language, uint32_t codepage = 0, uint32_t timestamp = 0); - -public: - //Helpers to add/replace resource - void add_resource(const std::string& data, resource_type type, - resource_directory_entry& new_entry, - const resource_directory::entry_finder& finder, - uint32_t language, uint32_t codepage, uint32_t timestamp); - - void add_resource(const std::string& data, const std::wstring& root_name, - resource_directory_entry& new_entry, - const resource_directory::entry_finder& finder, - uint32_t language, uint32_t codepage, uint32_t timestamp); - - void add_resource(const std::string& data, resource_directory_entry& new_root_entry, - const resource_directory::entry_finder& root_finder, - resource_directory_entry& new_entry, - const resource_directory::entry_finder& finder, - uint32_t language, uint32_t codepage, uint32_t timestamp); - -private: - //Root resource directory. We're not copying it, because it might be heavy - resource_directory& root_dir_edit_; - - //Helper to remove resource - bool remove_resource(const resource_directory::entry_finder& root_finder, const resource_directory::entry_finder& finder); - - //Helper to remove resource - bool remove_resource(const resource_directory::entry_finder& root_finder, const resource_directory::entry_finder& finder, uint32_t language); -}; -} diff --git a/tools/pe_bliss/pe_resource_viewer.cpp b/tools/pe_bliss/pe_resource_viewer.cpp deleted file mode 100644 index 712cc28d9b..0000000000 --- a/tools/pe_bliss/pe_resource_viewer.cpp +++ /dev/null @@ -1,382 +0,0 @@ -/*************************************************************************/ -/* Copyright (c) 2015 dx, http://kaimi.ru */ -/* */ -/* Permission is hereby granted, free of charge, to any person */ -/* obtaining a copy of this software and associated documentation */ -/* files (the "Software"), to deal in the Software without */ -/* restriction, including without limitation the rights to use, */ -/* copy, modify, merge, publish, distribute, sublicense, and/or */ -/* sell copies of the Software, and to permit persons to whom the */ -/* Software is furnished to do so, subject to the following conditions: */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#include <algorithm> -#include <cmath> -#include "pe_resource_viewer.h" -#include "pe_structures.h" - -namespace pe_bliss -{ -using namespace pe_win; - -//Constructor from root resource_directory -pe_resource_viewer::pe_resource_viewer(const resource_directory& root_directory) - :root_dir_(root_directory) -{} - -const resource_directory& pe_resource_viewer::get_root_directory() const -{ - return root_dir_; -} - -//Finder helpers -bool pe_resource_viewer::has_name::operator()(const resource_directory_entry& entry) const -{ - return entry.is_named(); -} - -bool pe_resource_viewer::has_id::operator()(const resource_directory_entry& entry) const -{ - return !entry.is_named(); -} - -//Lists resource types existing in PE file (non-named only) -const pe_resource_viewer::resource_type_list pe_resource_viewer::list_resource_types() const -{ - resource_type_list ret; - - //Get root directory entries list - const resource_directory::entry_list& entries = root_dir_.get_entry_list(); - for(resource_directory::entry_list::const_iterator it = entries.begin(); it != entries.end(); ++it) - { - //List all non-named items - if(!(*it).is_named()) - ret.push_back((*it).get_id()); - } - - return ret; -} - -//Returns true if resource type exists -bool pe_resource_viewer::resource_exists(resource_type type) const -{ - const resource_directory::entry_list& entries = root_dir_.get_entry_list(); - return std::find_if(entries.begin(), entries.end(), resource_directory::id_entry_finder(type)) != entries.end(); -} - -//Returns true if resource name exists -bool pe_resource_viewer::resource_exists(const std::wstring& root_name) const -{ - const resource_directory::entry_list& entries = root_dir_.get_entry_list(); - return std::find_if(entries.begin(), entries.end(), resource_directory::name_entry_finder(root_name)) != entries.end(); -} - -//Helper function to get name list from entry list -const pe_resource_viewer::resource_name_list pe_resource_viewer::get_name_list(const resource_directory::entry_list& entries) -{ - resource_name_list ret; - - for(resource_directory::entry_list::const_iterator it = entries.begin(); it != entries.end(); ++it) - { - //List all named items - if((*it).is_named()) - ret.push_back((*it).get_name()); - } - - return ret; -} - -//Helper function to get ID list from entry list -const pe_resource_viewer::resource_id_list pe_resource_viewer::get_id_list(const resource_directory::entry_list& entries) -{ - resource_id_list ret; - - for(resource_directory::entry_list::const_iterator it = entries.begin(); it != entries.end(); ++it) - { - //List all non-named items - if(!(*it).is_named()) - ret.push_back((*it).get_id()); - } - - return ret; -} - -//Lists resource names existing in PE file by resource type -const pe_resource_viewer::resource_name_list pe_resource_viewer::list_resource_names(resource_type type) const -{ - return get_name_list(root_dir_.entry_by_id(type).get_resource_directory().get_entry_list()); -} - -//Lists resource names existing in PE file by resource name -const pe_resource_viewer::resource_name_list pe_resource_viewer::list_resource_names(const std::wstring& root_name) const -{ - return get_name_list(root_dir_.entry_by_name(root_name).get_resource_directory().get_entry_list()); -} - -//Lists resource IDs existing in PE file by resource type -const pe_resource_viewer::resource_id_list pe_resource_viewer::list_resource_ids(resource_type type) const -{ - return get_id_list(root_dir_.entry_by_id(type).get_resource_directory().get_entry_list()); -} - -//Lists resource IDs existing in PE file by resource name -const pe_resource_viewer::resource_id_list pe_resource_viewer::list_resource_ids(const std::wstring& root_name) const -{ - return get_id_list(root_dir_.entry_by_name(root_name).get_resource_directory().get_entry_list()); -} - -//Returns resource count by type -unsigned long pe_resource_viewer::get_resource_count(resource_type type) const -{ - return static_cast<unsigned long>( - root_dir_ //Type directory - .entry_by_id(type) - .get_resource_directory() //Name/ID directory - .get_entry_list() - .size()); -} - -//Returns resource count by name -unsigned long pe_resource_viewer::get_resource_count(const std::wstring& root_name) const -{ - return static_cast<unsigned long>( - root_dir_ //Type directory - .entry_by_name(root_name) - .get_resource_directory() //Name/ID directory - .get_entry_list() - .size()); -} - -//Returns language count of resource by resource type and name -unsigned long pe_resource_viewer::get_language_count(resource_type type, const std::wstring& name) const -{ - const resource_directory::entry_list& entries = - root_dir_ //Type directory - .entry_by_id(type) - .get_resource_directory() //Name/ID directory - .entry_by_name(name) - .get_resource_directory() //Language directory - .get_entry_list(); - - return static_cast<unsigned long>(std::count_if(entries.begin(), entries.end(), has_id())); -} - -//Returns language count of resource by resource names -unsigned long pe_resource_viewer::get_language_count(const std::wstring& root_name, const std::wstring& name) const -{ - const resource_directory::entry_list& entries = - root_dir_ //Type directory - .entry_by_name(root_name) - .get_resource_directory() //Name/ID directory - .entry_by_name(name) - .get_resource_directory() //Language directory - .get_entry_list(); - - return static_cast<unsigned long>(std::count_if(entries.begin(), entries.end(), has_id())); -} - -//Returns language count of resource by resource type and ID -unsigned long pe_resource_viewer::get_language_count(resource_type type, uint32_t id) const -{ - const resource_directory::entry_list& entries = - root_dir_ //Type directory - .entry_by_id(type) - .get_resource_directory() //Name/ID directory - .entry_by_id(id) - .get_resource_directory() //Language directory - .get_entry_list(); - - return static_cast<unsigned long>(std::count_if(entries.begin(), entries.end(), has_id())); -} - -//Returns language count of resource by resource name and ID -unsigned long pe_resource_viewer::get_language_count(const std::wstring& root_name, uint32_t id) const -{ - const resource_directory::entry_list& entries = - root_dir_ //Type directory - .entry_by_name(root_name) - .get_resource_directory() //Name/ID directory - .entry_by_id(id) - .get_resource_directory() //Language directory - .get_entry_list(); - - return static_cast<unsigned long>(std::count_if(entries.begin(), entries.end(), has_id())); -} - -//Lists resource languages by resource type and name -const pe_resource_viewer::resource_language_list pe_resource_viewer::list_resource_languages(resource_type type, const std::wstring& name) const -{ - const resource_directory::entry_list& entries = - root_dir_ //Type directory - .entry_by_id(type) - .get_resource_directory() //Name/ID directory - .entry_by_name(name) - .get_resource_directory() //Language directory - .get_entry_list(); - - return get_id_list(entries); -} - -//Lists resource languages by resource names -const pe_resource_viewer::resource_language_list pe_resource_viewer::list_resource_languages(const std::wstring& root_name, const std::wstring& name) const -{ - const resource_directory::entry_list& entries = - root_dir_ //Type directory - .entry_by_name(root_name) - .get_resource_directory() //Name/ID directory - .entry_by_name(name) - .get_resource_directory() //Language directory - .get_entry_list(); - - return get_id_list(entries); -} - -//Lists resource languages by resource type and ID -const pe_resource_viewer::resource_language_list pe_resource_viewer::list_resource_languages(resource_type type, uint32_t id) const -{ - const resource_directory::entry_list& entries = - root_dir_ //Type directory - .entry_by_id(type) - .get_resource_directory() //Name/ID directory - .entry_by_id(id) - .get_resource_directory() //Language directory - .get_entry_list(); - - return get_id_list(entries); -} - -//Lists resource languages by resource name and ID -const pe_resource_viewer::resource_language_list pe_resource_viewer::list_resource_languages(const std::wstring& root_name, uint32_t id) const -{ - const resource_directory::entry_list& entries = - root_dir_ //Type directory - .entry_by_name(root_name) - .get_resource_directory() //Name/ID directory - .entry_by_id(id) - .get_resource_directory() //Language directory - .get_entry_list(); - - return get_id_list(entries); -} - -//Returns raw resource data by type, name and language -const resource_data_info pe_resource_viewer::get_resource_data_by_name(uint32_t language, resource_type type, const std::wstring& name) const -{ - return resource_data_info(root_dir_ //Type directory - .entry_by_id(type) - .get_resource_directory() //Name/ID directory - .entry_by_name(name) - .get_resource_directory() //Language directory - .entry_by_id(language) - .get_data_entry()); //Data directory -} - -//Returns raw resource data by root name, name and language -const resource_data_info pe_resource_viewer::get_resource_data_by_name(uint32_t language, const std::wstring& root_name, const std::wstring& name) const -{ - return resource_data_info(root_dir_ //Type directory - .entry_by_name(root_name) - .get_resource_directory() //Name/ID directory - .entry_by_name(name) - .get_resource_directory() //Language directory - .entry_by_id(language) - .get_data_entry()); //Data directory -} - -//Returns raw resource data by type, ID and language -const resource_data_info pe_resource_viewer::get_resource_data_by_id(uint32_t language, resource_type type, uint32_t id) const -{ - return resource_data_info(root_dir_ //Type directory - .entry_by_id(type) - .get_resource_directory() //Name/ID directory - .entry_by_id(id) - .get_resource_directory() //Language directory - .entry_by_id(language) - .get_data_entry()); //Data directory -} - -//Returns raw resource data by root name, ID and language -const resource_data_info pe_resource_viewer::get_resource_data_by_id(uint32_t language, const std::wstring& root_name, uint32_t id) const -{ - return resource_data_info(root_dir_ //Type directory - .entry_by_name(root_name) - .get_resource_directory() //Name/ID directory - .entry_by_id(id) - .get_resource_directory() //Language directory - .entry_by_id(language) - .get_data_entry()); //Data directory -} - -//Returns raw resource data by type, name and index in language directory (instead of language) -const resource_data_info pe_resource_viewer::get_resource_data_by_name(resource_type type, const std::wstring& name, uint32_t index) const -{ - const resource_directory::entry_list& entries = root_dir_ //Type directory - .entry_by_id(type) - .get_resource_directory() //Name/ID directory - .entry_by_name(name) - .get_resource_directory() //Language directory - .get_entry_list(); - - if(entries.size() <= index) - throw pe_exception("Resource data entry not found", pe_exception::resource_data_entry_not_found); - - return resource_data_info(entries.at(index).get_data_entry()); //Data directory -} - -//Returns raw resource data by root name, name and index in language directory (instead of language) -const resource_data_info pe_resource_viewer::get_resource_data_by_name(const std::wstring& root_name, const std::wstring& name, uint32_t index) const -{ - const resource_directory::entry_list& entries = root_dir_ //Type directory - .entry_by_name(root_name) - .get_resource_directory() //Name/ID directory - .entry_by_name(name) - .get_resource_directory() //Language directory - .get_entry_list(); - - if(entries.size() <= index) - throw pe_exception("Resource data entry not found", pe_exception::resource_data_entry_not_found); - - return resource_data_info(entries.at(index).get_data_entry()); //Data directory -} - -//Returns raw resource data by type, ID and index in language directory (instead of language) -const resource_data_info pe_resource_viewer::get_resource_data_by_id(resource_type type, uint32_t id, uint32_t index) const -{ - const resource_directory::entry_list& entries = root_dir_ //Type directory - .entry_by_id(type) - .get_resource_directory() //Name/ID directory - .entry_by_id(id) - .get_resource_directory() //Language directory - .get_entry_list(); - - if(entries.size() <= index) - throw pe_exception("Resource data entry not found", pe_exception::resource_data_entry_not_found); - - return resource_data_info(entries.at(index).get_data_entry()); //Data directory -} - -//Returns raw resource data by root name, ID and index in language directory (instead of language) -const resource_data_info pe_resource_viewer::get_resource_data_by_id(const std::wstring& root_name, uint32_t id, uint32_t index) const -{ - const resource_directory::entry_list& entries = root_dir_ //Type directory - .entry_by_name(root_name) - .get_resource_directory() //Name/ID directory - .entry_by_id(id) - .get_resource_directory() //Language directory - .get_entry_list(); - - if(entries.size() <= index) - throw pe_exception("Resource data entry not found", pe_exception::resource_data_entry_not_found); - - return resource_data_info(entries.at(index).get_data_entry()); //Data directory -} -} diff --git a/tools/pe_bliss/pe_resource_viewer.h b/tools/pe_bliss/pe_resource_viewer.h deleted file mode 100644 index e585da6a87..0000000000 --- a/tools/pe_bliss/pe_resource_viewer.h +++ /dev/null @@ -1,153 +0,0 @@ -/*************************************************************************/ -/* Copyright (c) 2015 dx, http://kaimi.ru */ -/* */ -/* Permission is hereby granted, free of charge, to any person */ -/* obtaining a copy of this software and associated documentation */ -/* files (the "Software"), to deal in the Software without */ -/* restriction, including without limitation the rights to use, */ -/* copy, modify, merge, publish, distribute, sublicense, and/or */ -/* sell copies of the Software, and to permit persons to whom the */ -/* Software is furnished to do so, subject to the following conditions: */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#pragma once -#include <map> -#include <string> -#include "pe_structures.h" -#include "pe_resources.h" -#include "message_table.h" -#include "resource_data_info.h" - -namespace pe_bliss -{ - //PE resource manager allows to read resources from PE files -class pe_resource_viewer -{ -public: - //Resource type enumeration - enum resource_type - { - resource_cursor = 1, - resource_bitmap = 2, - resource_icon = 3, - resource_menu = 4, - resource_dialog = 5, - resource_string = 6, - resource_fontdir = 7, - resource_font = 8, - resource_accelerator = 9, - resource_rcdata = 10, - resource_message_table = 11, - resource_cursor_group = 12, - resource_icon_group = 14, - resource_version = 16, - resource_dlginclude = 17, - resource_plugplay = 19, - resource_vxd = 20, - resource_anicursor = 21, - resource_aniicon = 22, - resource_html = 23, - resource_manifest = 24 - }; - -public: - //Some useful typedefs - typedef std::vector<uint32_t> resource_type_list; - typedef std::vector<uint32_t> resource_id_list; - typedef std::vector<std::wstring> resource_name_list; - typedef std::vector<uint32_t> resource_language_list; - -public: - //Constructor from root resource_directory from PE file - explicit pe_resource_viewer(const resource_directory& root_directory); - - const resource_directory& get_root_directory() const; - - //Lists resource types existing in PE file (non-named only) - const resource_type_list list_resource_types() const; - //Returns true if resource type exists - bool resource_exists(resource_type type) const; - //Returns true if resource name exists - bool resource_exists(const std::wstring& root_name) const; - - //Lists resource names existing in PE file by resource type - const resource_name_list list_resource_names(resource_type type) const; - //Lists resource names existing in PE file by resource name - const resource_name_list list_resource_names(const std::wstring& root_name) const; - //Lists resource IDs existing in PE file by resource type - const resource_id_list list_resource_ids(resource_type type) const; - //Lists resource IDs existing in PE file by resource name - const resource_id_list list_resource_ids(const std::wstring& root_name) const; - //Returns resource count by type - unsigned long get_resource_count(resource_type type) const; - //Returns resource count by name - unsigned long get_resource_count(const std::wstring& root_name) const; - - //Returns language count of resource by resource type and name - unsigned long get_language_count(resource_type type, const std::wstring& name) const; - //Returns language count of resource by resource names - unsigned long get_language_count(const std::wstring& root_name, const std::wstring& name) const; - //Returns language count of resource by resource type and ID - unsigned long get_language_count(resource_type type, uint32_t id) const; - //Returns language count of resource by resource name and ID - unsigned long get_language_count(const std::wstring& root_name, uint32_t id) const; - //Lists resource languages by resource type and name - const resource_language_list list_resource_languages(resource_type type, const std::wstring& name) const; - //Lists resource languages by resource names - const resource_language_list list_resource_languages(const std::wstring& root_name, const std::wstring& name) const; - //Lists resource languages by resource type and ID - const resource_language_list list_resource_languages(resource_type type, uint32_t id) const; - //Lists resource languages by resource name and ID - const resource_language_list list_resource_languages(const std::wstring& root_name, uint32_t id) const; - - //Returns raw resource data by type, name and language - const resource_data_info get_resource_data_by_name(uint32_t language, resource_type type, const std::wstring& name) const; - //Returns raw resource data by root name, name and language - const resource_data_info get_resource_data_by_name(uint32_t language, const std::wstring& root_name, const std::wstring& name) const; - //Returns raw resource data by type, ID and language - const resource_data_info get_resource_data_by_id(uint32_t language, resource_type type, uint32_t id) const; - //Returns raw resource data by root name, ID and language - const resource_data_info get_resource_data_by_id(uint32_t language, const std::wstring& root_name, uint32_t id) const; - //Returns raw resource data by type, name and index in language directory (instead of language) - const resource_data_info get_resource_data_by_name(resource_type type, const std::wstring& name, uint32_t index = 0) const; - //Returns raw resource data by root name, name and index in language directory (instead of language) - const resource_data_info get_resource_data_by_name(const std::wstring& root_name, const std::wstring& name, uint32_t index = 0) const; - //Returns raw resource data by type, ID and index in language directory (instead of language) - const resource_data_info get_resource_data_by_id(resource_type type, uint32_t id, uint32_t index = 0) const; - //Returns raw resource data by root name, ID and index in language directory (instead of language) - const resource_data_info get_resource_data_by_id(const std::wstring& root_name, uint32_t id, uint32_t index = 0) const; - -protected: - //Root resource directory. We're not copying it, because it might be heavy - const resource_directory& root_dir_; - - //Helper function to get ID list from entry list - static const resource_id_list get_id_list(const resource_directory::entry_list& entries); - //Helper function to get name list from entry list - static const resource_name_list get_name_list(const resource_directory::entry_list& entries); - -protected: - //Helper structure - finder of resource_directory_entry that is named - struct has_name - { - public: - bool operator()(const resource_directory_entry& entry) const; - }; - - //Helper structure - finder of resource_directory_entry that is not named (has id) - struct has_id - { - public: - bool operator()(const resource_directory_entry& entry) const; - }; -}; -} diff --git a/tools/pe_bliss/pe_resources.cpp b/tools/pe_bliss/pe_resources.cpp deleted file mode 100644 index 189aba1f76..0000000000 --- a/tools/pe_bliss/pe_resources.cpp +++ /dev/null @@ -1,726 +0,0 @@ -/*************************************************************************/ -/* Copyright (c) 2015 dx, http://kaimi.ru */ -/* */ -/* Permission is hereby granted, free of charge, to any person */ -/* obtaining a copy of this software and associated documentation */ -/* files (the "Software"), to deal in the Software without */ -/* restriction, including without limitation the rights to use, */ -/* copy, modify, merge, publish, distribute, sublicense, and/or */ -/* sell copies of the Software, and to permit persons to whom the */ -/* Software is furnished to do so, subject to the following conditions: */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#include <algorithm> -#include <string.h> -#include "pe_resources.h" - -namespace pe_bliss -{ -using namespace pe_win; - -//RESOURCES -//Default constructor -resource_data_entry::resource_data_entry() - :codepage_(0) -{} - -//Constructor from data -resource_data_entry::resource_data_entry(const std::string& data, uint32_t codepage) - :codepage_(codepage), data_(data) -{} - -//Returns resource data codepage -uint32_t resource_data_entry::get_codepage() const -{ - return codepage_; -} - -//Returns resource data -const std::string& resource_data_entry::get_data() const -{ - return data_; -} - -//Sets resource data codepage -void resource_data_entry::set_codepage(uint32_t codepage) -{ - codepage_ = codepage; -} - -//Sets resource data -void resource_data_entry::set_data(const std::string& data) -{ - data_ = data; -} - -//Default constructor -resource_directory_entry::includes::includes() - :data_(0) -{} - -//Default constructor -resource_directory_entry::resource_directory_entry() - :id_(0), includes_data_(false), named_(false) -{} - -//Copy constructor -resource_directory_entry::resource_directory_entry(const resource_directory_entry& other) - :id_(other.id_), name_(other.name_), includes_data_(other.includes_data_), named_(other.named_) -{ - //If union'ed pointer is not zero - if(other.ptr_.data_) - { - if(other.includes_data()) - ptr_.data_ = new resource_data_entry(*other.ptr_.data_); - else - ptr_.dir_ = new resource_directory(*other.ptr_.dir_); - } -} - -//Copy assignment operator -resource_directory_entry& resource_directory_entry::operator=(const resource_directory_entry& other) -{ - release(); - - id_ = other.id_; - name_ = other.name_; - includes_data_ = other.includes_data_; - named_ = other.named_; - - //If other union'ed pointer is not zero - if(other.ptr_.data_) - { - if(other.includes_data()) - ptr_.data_ = new resource_data_entry(*other.ptr_.data_); - else - ptr_.dir_ = new resource_directory(*other.ptr_.dir_); - } - - return *this; -} - -//Destroys included data -void resource_directory_entry::release() -{ - //If union'ed pointer is not zero - if(ptr_.data_) - { - if(includes_data()) - delete ptr_.data_; - else - delete ptr_.dir_; - - ptr_.data_ = 0; - } -} - -//Destructor -resource_directory_entry::~resource_directory_entry() -{ - release(); -} - -//Returns entry ID -uint32_t resource_directory_entry::get_id() const -{ - return id_; -} - -//Returns entry name -const std::wstring& resource_directory_entry::get_name() const -{ - return name_; -} - -//Returns true, if entry has name -//Returns false, if entry has ID -bool resource_directory_entry::is_named() const -{ - return named_; -} - -//Returns true, if entry includes resource_data_entry -//Returns false, if entry includes resource_directory -bool resource_directory_entry::includes_data() const -{ - return includes_data_; -} - -//Returns resource_directory if entry includes it, otherwise throws an exception -const resource_directory& resource_directory_entry::get_resource_directory() const -{ - if(!ptr_.dir_ || includes_data_) - throw pe_exception("Resource directory entry does not contain resource directory", pe_exception::resource_directory_entry_error); - - return *ptr_.dir_; -} - -//Returns resource_data_entry if entry includes it, otherwise throws an exception -const resource_data_entry& resource_directory_entry::get_data_entry() const -{ - if(!ptr_.data_ || !includes_data_) - throw pe_exception("Resource directory entry does not contain resource data entry", pe_exception::resource_directory_entry_error); - - return *ptr_.data_; -} - -//Returns resource_directory if entry includes it, otherwise throws an exception -resource_directory& resource_directory_entry::get_resource_directory() -{ - if(!ptr_.dir_ || includes_data_) - throw pe_exception("Resource directory entry does not contain resource directory", pe_exception::resource_directory_entry_error); - - return *ptr_.dir_; -} - -//Returns resource_data_entry if entry includes it, otherwise throws an exception -resource_data_entry& resource_directory_entry::get_data_entry() -{ - if(!ptr_.data_ || !includes_data_) - throw pe_exception("Resource directory entry does not contain resource data entry", pe_exception::resource_directory_entry_error); - - return *ptr_.data_; -} - -//Sets entry name -void resource_directory_entry::set_name(const std::wstring& name) -{ - name_ = name; - named_ = true; - id_ = 0; -} - -//Sets entry ID -void resource_directory_entry::set_id(uint32_t id) -{ - id_ = id; - named_ = false; - name_.clear(); -} - -//Adds resource_data_entry -void resource_directory_entry::add_data_entry(const resource_data_entry& entry) -{ - release(); - ptr_.data_ = new resource_data_entry(entry); - includes_data_ = true; -} - -//Adds resource_directory -void resource_directory_entry::add_resource_directory(const resource_directory& dir) -{ - release(); - ptr_.dir_ = new resource_directory(dir); - includes_data_ = false; -} - -//Default constructor -resource_directory::resource_directory() - :characteristics_(0), - timestamp_(0), - major_version_(0), minor_version_(0), - number_of_named_entries_(0), number_of_id_entries_(0) -{} - -//Constructor from data -resource_directory::resource_directory(const image_resource_directory& dir) - :characteristics_(dir.Characteristics), - timestamp_(dir.TimeDateStamp), - major_version_(dir.MajorVersion), minor_version_(dir.MinorVersion), - number_of_named_entries_(0), number_of_id_entries_(0) //Set to zero here, calculate on add -{} - -//Returns characteristics of directory -uint32_t resource_directory::get_characteristics() const -{ - return characteristics_; -} - -//Returns date and time stamp of directory -uint32_t resource_directory::get_timestamp() const -{ - return timestamp_; -} - -//Returns major version of directory -uint16_t resource_directory::get_major_version() const -{ - return major_version_; -} - -//Returns minor version of directory -uint16_t resource_directory::get_minor_version() const -{ - return minor_version_; -} - -//Returns number of named entries -uint32_t resource_directory::get_number_of_named_entries() const -{ - return number_of_named_entries_; -} - -//Returns number of ID entries -uint32_t resource_directory::get_number_of_id_entries() const -{ - return number_of_id_entries_; -} - -//Returns resource_directory_entry array -const resource_directory::entry_list& resource_directory::get_entry_list() const -{ - return entries_; -} - -//Returns resource_directory_entry array -resource_directory::entry_list& resource_directory::get_entry_list() -{ - return entries_; -} - -//Adds resource_directory_entry -void resource_directory::add_resource_directory_entry(const resource_directory_entry& entry) -{ - entries_.push_back(entry); - if(entry.is_named()) - ++number_of_named_entries_; - else - ++number_of_id_entries_; -} - -//Clears resource_directory_entry array -void resource_directory::clear_resource_directory_entry_list() -{ - entries_.clear(); - number_of_named_entries_ = 0; - number_of_id_entries_ = 0; -} - -//Sets characteristics of directory -void resource_directory::set_characteristics(uint32_t characteristics) -{ - characteristics_ = characteristics; -} - -//Sets date and time stamp of directory -void resource_directory::set_timestamp(uint32_t timestamp) -{ - timestamp_ = timestamp; -} - -//Sets number of named entries -void resource_directory::set_number_of_named_entries(uint32_t number) -{ - number_of_named_entries_ = number; -} - -//Sets number of ID entries -void resource_directory::set_number_of_id_entries(uint32_t number) -{ - number_of_id_entries_ = number; -} - -//Sets major version of directory -void resource_directory::set_major_version(uint16_t major_version) -{ - major_version_ = major_version; -} - -//Sets minor version of directory -void resource_directory::get_minor_version(uint16_t minor_version) -{ - minor_version_ = minor_version; -} - -//Processes resource directory -const resource_directory process_resource_directory(const pe_base& pe, uint32_t res_rva, uint32_t offset_to_directory, std::set<uint32_t>& processed) -{ - resource_directory ret; - - //Check for resource loops - if(!processed.insert(offset_to_directory).second) - throw pe_exception("Incorrect resource directory", pe_exception::incorrect_resource_directory); - - if(!pe_utils::is_sum_safe(res_rva, offset_to_directory)) - throw pe_exception("Incorrect resource directory", pe_exception::incorrect_resource_directory); - - //Get root IMAGE_RESOURCE_DIRECTORY - image_resource_directory directory = pe.section_data_from_rva<image_resource_directory>(res_rva + offset_to_directory, section_data_virtual, true); - - ret = resource_directory(directory); - - //Check DWORDs for possible overflows - if(!pe_utils::is_sum_safe(directory.NumberOfIdEntries, directory.NumberOfNamedEntries) - || directory.NumberOfIdEntries + directory.NumberOfNamedEntries >= pe_utils::max_dword / sizeof(image_resource_directory_entry) + sizeof(image_resource_directory)) - throw pe_exception("Incorrect resource directory", pe_exception::incorrect_resource_directory); - - if(!pe_utils::is_sum_safe(offset_to_directory, sizeof(image_resource_directory) + (directory.NumberOfIdEntries + directory.NumberOfNamedEntries) * sizeof(image_resource_directory_entry)) - || !pe_utils::is_sum_safe(res_rva, offset_to_directory + sizeof(image_resource_directory) + (directory.NumberOfIdEntries + directory.NumberOfNamedEntries) * sizeof(image_resource_directory_entry))) - throw pe_exception("Incorrect resource directory", pe_exception::incorrect_resource_directory); - - for(unsigned long i = 0; i != static_cast<unsigned long>(directory.NumberOfIdEntries) + directory.NumberOfNamedEntries; ++i) - { - //Read directory entries one by one - image_resource_directory_entry dir_entry = pe.section_data_from_rva<image_resource_directory_entry>( - res_rva + sizeof(image_resource_directory) + i * sizeof(image_resource_directory_entry) + offset_to_directory, section_data_virtual, true); - - //Create directory entry structure - resource_directory_entry entry; - - //If directory is named - if(dir_entry.NameIsString) - { - if(!pe_utils::is_sum_safe(res_rva + sizeof(uint16_t) /* safe */, dir_entry.NameOffset)) - throw pe_exception("Incorrect resource directory", pe_exception::incorrect_resource_directory); - - //get directory name length - uint16_t directory_name_length = pe.section_data_from_rva<uint16_t>(res_rva + dir_entry.NameOffset, section_data_virtual, true); - - //Check name length - if(pe.section_data_length_from_rva(res_rva + dir_entry.NameOffset + sizeof(uint16_t), res_rva + dir_entry.NameOffset + sizeof(uint16_t), section_data_virtual, true) - < directory_name_length) - throw pe_exception("Incorrect resource directory", pe_exception::incorrect_resource_directory); - -#ifdef PE_BLISS_WINDOWS - //Set entry UNICODE name - entry.set_name(std::wstring( - reinterpret_cast<const wchar_t*>(pe.section_data_from_rva(res_rva + dir_entry.NameOffset + sizeof(uint16_t), section_data_virtual, true)), - directory_name_length)); -#else - //Set entry UNICODE name - entry.set_name(pe_utils::from_ucs2(u16string( - reinterpret_cast<const unicode16_t*>(pe.section_data_from_rva(res_rva + dir_entry.NameOffset + sizeof(uint16_t), section_data_virtual, true)), - directory_name_length))); -#endif - } - else - { - //Else - set directory ID - entry.set_id(dir_entry.Id); - } - - //If directory entry has another resource directory - if(dir_entry.DataIsDirectory) - { - entry.add_resource_directory(process_resource_directory(pe, res_rva, dir_entry.OffsetToDirectory, processed)); - } - else - { - //If directory entry has data - image_resource_data_entry data_entry = pe.section_data_from_rva<image_resource_data_entry>( - res_rva + dir_entry.OffsetToData, section_data_virtual, true); - - //Check byte count that stated by data entry - if(pe.section_data_length_from_rva(data_entry.OffsetToData, data_entry.OffsetToData, section_data_virtual, true) < data_entry.Size) - throw pe_exception("Incorrect resource directory", pe_exception::incorrect_resource_directory); - - //Add data entry to directory entry - entry.add_data_entry(resource_data_entry( - std::string(pe.section_data_from_rva(data_entry.OffsetToData, section_data_virtual, true), data_entry.Size), - data_entry.CodePage)); - } - - //Save directory entry - ret.add_resource_directory_entry(entry); - } - - //Return resource directory - return ret; -} - -//Helper function to calculate needed space for resource data -void calculate_resource_data_space(const resource_directory& root, uint32_t aligned_offset_from_section_start, uint32_t& needed_size_for_structures, uint32_t& needed_size_for_strings) -{ - needed_size_for_structures += sizeof(image_resource_directory); - for(resource_directory::entry_list::const_iterator it = root.get_entry_list().begin(); it != root.get_entry_list().end(); ++it) - { - needed_size_for_structures += sizeof(image_resource_directory_entry); - - if((*it).is_named()) - needed_size_for_strings += static_cast<uint32_t>(((*it).get_name().length() + 1) * 2 /* unicode */ + sizeof(uint16_t) /* for string length */); - - if(!(*it).includes_data()) - calculate_resource_data_space((*it).get_resource_directory(), aligned_offset_from_section_start, needed_size_for_structures, needed_size_for_strings); - } -} - -//Helper function to calculate needed space for resource data -void calculate_resource_data_space(const resource_directory& root, uint32_t needed_size_for_structures, uint32_t needed_size_for_strings, uint32_t& needed_size_for_data, uint32_t& current_data_pos) -{ - for(resource_directory::entry_list::const_iterator it = root.get_entry_list().begin(); it != root.get_entry_list().end(); ++it) - { - if((*it).includes_data()) - { - uint32_t data_size = static_cast<uint32_t>((*it).get_data_entry().get_data().length() - + sizeof(image_resource_data_entry) - + (pe_utils::align_up(current_data_pos, sizeof(uint32_t)) - current_data_pos) /* alignment */); - needed_size_for_data += data_size; - current_data_pos += data_size; - } - else - { - calculate_resource_data_space((*it).get_resource_directory(), needed_size_for_structures, needed_size_for_strings, needed_size_for_data, current_data_pos); - } - } -} - -//Helper: sorts resource directory entries -struct entry_sorter -{ -public: - bool operator()(const resource_directory_entry& entry1, const resource_directory_entry& entry2) const; -}; - -//Helper function to rebuild resource directory -void rebuild_resource_directory(pe_base& pe, section& resource_section, resource_directory& root, uint32_t& current_structures_pos, uint32_t& current_data_pos, uint32_t& current_strings_pos, uint32_t offset_from_section_start) -{ - //Create resource directory - image_resource_directory dir = {0}; - dir.Characteristics = root.get_characteristics(); - dir.MajorVersion = root.get_major_version(); - dir.MinorVersion = root.get_minor_version(); - dir.TimeDateStamp = root.get_timestamp(); - - { - resource_directory::entry_list& entries = root.get_entry_list(); - std::sort(entries.begin(), entries.end(), entry_sorter()); - } - - //Calculate number of named and ID entries - for(resource_directory::entry_list::const_iterator it = root.get_entry_list().begin(); it != root.get_entry_list().end(); ++it) - { - if((*it).is_named()) - ++dir.NumberOfNamedEntries; - else - ++dir.NumberOfIdEntries; - } - - std::string& raw_data = resource_section.get_raw_data(); - - //Save resource directory - memcpy(&raw_data[current_structures_pos], &dir, sizeof(dir)); - current_structures_pos += sizeof(dir); - - uint32_t this_current_structures_pos = current_structures_pos; - - current_structures_pos += sizeof(image_resource_directory_entry) * (dir.NumberOfNamedEntries + dir.NumberOfIdEntries); - - //Create all resource directory entries - for(resource_directory::entry_list::iterator it = root.get_entry_list().begin(); it != root.get_entry_list().end(); ++it) - { - image_resource_directory_entry entry; - if((*it).is_named()) - { - entry.Name = 0x80000000 | (current_strings_pos - offset_from_section_start); - uint16_t unicode_length = static_cast<uint16_t>((*it).get_name().length()); - memcpy(&raw_data[current_strings_pos], &unicode_length, sizeof(unicode_length)); - current_strings_pos += sizeof(unicode_length); - -#ifdef PE_BLISS_WINDOWS - memcpy(&raw_data[current_strings_pos], (*it).get_name().c_str(), (*it).get_name().length() * sizeof(uint16_t) + sizeof(uint16_t) /* unicode */); -#else - { - u16string str(pe_utils::to_ucs2((*it).get_name())); - memcpy(&raw_data[current_strings_pos], str.c_str(), (*it).get_name().length() * sizeof(uint16_t) + sizeof(uint16_t) /* unicode */); - } -#endif - - current_strings_pos += static_cast<unsigned long>((*it).get_name().length() * sizeof(uint16_t) + sizeof(uint16_t) /* unicode */); - } - else - { - entry.Name = (*it).get_id(); - } - - if((*it).includes_data()) - { - current_data_pos = pe_utils::align_up(current_data_pos, sizeof(uint32_t)); - image_resource_data_entry data_entry = {0}; - data_entry.CodePage = (*it).get_data_entry().get_codepage(); - data_entry.Size = static_cast<uint32_t>((*it).get_data_entry().get_data().length()); - data_entry.OffsetToData = pe.rva_from_section_offset(resource_section, current_data_pos + sizeof(data_entry)); - - entry.OffsetToData = current_data_pos - offset_from_section_start; - - memcpy(&raw_data[current_data_pos], &data_entry, sizeof(data_entry)); - current_data_pos += sizeof(data_entry); - - memcpy(&raw_data[current_data_pos], (*it).get_data_entry().get_data().data(), data_entry.Size); - current_data_pos += data_entry.Size; - - memcpy(&raw_data[this_current_structures_pos], &entry, sizeof(entry)); - this_current_structures_pos += sizeof(entry); - } - else - { - entry.OffsetToData = 0x80000000 | (current_structures_pos - offset_from_section_start); - - memcpy(&raw_data[this_current_structures_pos], &entry, sizeof(entry)); - this_current_structures_pos += sizeof(entry); - - rebuild_resource_directory(pe, resource_section, (*it).get_resource_directory(), current_structures_pos, current_data_pos, current_strings_pos, offset_from_section_start); - } - } -} - -//Helper function to rebuild resource directory -bool entry_sorter::operator()(const resource_directory_entry& entry1, const resource_directory_entry& entry2) const -{ - if(entry1.is_named() && entry2.is_named()) - return entry1.get_name() < entry2.get_name(); - else if(!entry1.is_named() && !entry2.is_named()) - return entry1.get_id() < entry2.get_id(); - else - return entry1.is_named(); -} - -//Resources rebuilder -//resource_directory - root resource directory -//resources_section - section where resource directory will be placed (must be attached to PE image) -//offset_from_section_start - offset from resources_section raw data start -//resource_directory is non-constant, because it will be sorted -//save_to_pe_headers - if true, new resource directory information will be saved to PE image headers -//auto_strip_last_section - if true and resources are placed in the last section, it will be automatically stripped -//number_of_id_entries and number_of_named_entries for resource directories are recalculated and not used -const image_directory rebuild_resources(pe_base& pe, resource_directory& info, section& resources_section, uint32_t offset_from_section_start, bool save_to_pe_header, bool auto_strip_last_section) -{ - //Check that resources_section is attached to this PE image - if(!pe.section_attached(resources_section)) - throw pe_exception("Resource section must be attached to PE file", pe_exception::section_is_not_attached); - - //Check resource directory correctness - if(info.get_entry_list().empty()) - throw pe_exception("Empty resource directory", pe_exception::incorrect_resource_directory); - - uint32_t aligned_offset_from_section_start = pe_utils::align_up(offset_from_section_start, sizeof(uint32_t)); - uint32_t needed_size_for_structures = aligned_offset_from_section_start - offset_from_section_start; //Calculate needed size for resource tables and data - uint32_t needed_size_for_strings = 0; - uint32_t needed_size_for_data = 0; - - calculate_resource_data_space(info, aligned_offset_from_section_start, needed_size_for_structures, needed_size_for_strings); - - { - uint32_t current_data_pos = aligned_offset_from_section_start + needed_size_for_structures + needed_size_for_strings; - calculate_resource_data_space(info, needed_size_for_structures, needed_size_for_strings, needed_size_for_data, current_data_pos); - } - - uint32_t needed_size = needed_size_for_structures + needed_size_for_strings + needed_size_for_data; - - //Check if resources_section is last one. If it's not, check if there's enough place for resource data - if(&resources_section != &*(pe.get_image_sections().end() - 1) && - (resources_section.empty() || pe_utils::align_up(resources_section.get_size_of_raw_data(), pe.get_file_alignment()) - < needed_size + aligned_offset_from_section_start)) - throw pe_exception("Insufficient space for resource directory", pe_exception::insufficient_space); - - std::string& raw_data = resources_section.get_raw_data(); - - //This will be done only if resources_section is the last section of image or for section with unaligned raw length of data - if(raw_data.length() < needed_size + aligned_offset_from_section_start) - raw_data.resize(needed_size + aligned_offset_from_section_start); //Expand section raw data - - uint32_t current_structures_pos = aligned_offset_from_section_start; - uint32_t current_strings_pos = current_structures_pos + needed_size_for_structures; - uint32_t current_data_pos = current_strings_pos + needed_size_for_strings; - rebuild_resource_directory(pe, resources_section, info, current_structures_pos, current_data_pos, current_strings_pos, aligned_offset_from_section_start); - - //Adjust section raw and virtual sizes - pe.recalculate_section_sizes(resources_section, auto_strip_last_section); - - image_directory ret(pe.rva_from_section_offset(resources_section, aligned_offset_from_section_start), needed_size); - - //If auto-rewrite of PE headers is required - if(save_to_pe_header) - { - pe.set_directory_rva(image_directory_entry_resource, ret.get_rva()); - pe.set_directory_size(image_directory_entry_resource, ret.get_size()); - } - - return ret; -} - -//Returns resources from PE file -const resource_directory get_resources(const pe_base& pe) -{ - resource_directory ret; - - if(!pe.has_resources()) - return ret; - - //Get resource directory RVA - uint32_t res_rva = pe.get_directory_rva(image_directory_entry_resource); - - //Store already processed directories to avoid resource loops - std::set<uint32_t> processed; - - //Process all directories (recursion) - ret = process_resource_directory(pe, res_rva, 0, processed); - - return ret; -} - -//Finds resource_directory_entry by ID -resource_directory::id_entry_finder::id_entry_finder(uint32_t id) - :id_(id) -{} - -bool resource_directory::id_entry_finder::operator()(const resource_directory_entry& entry) const -{ - return !entry.is_named() && entry.get_id() == id_; -} - -//Finds resource_directory_entry by name -resource_directory::name_entry_finder::name_entry_finder(const std::wstring& name) - :name_(name) -{} - -bool resource_directory::name_entry_finder::operator()(const resource_directory_entry& entry) const -{ - return entry.is_named() && entry.get_name() == name_; -} - -//Finds resource_directory_entry by name or ID (universal) -resource_directory::entry_finder::entry_finder(const std::wstring& name) - :name_(name), named_(true) -{} - -resource_directory::entry_finder::entry_finder(uint32_t id) - :id_(id), named_(false) -{} - -bool resource_directory::entry_finder::operator()(const resource_directory_entry& entry) const -{ - if(named_) - return entry.is_named() && entry.get_name() == name_; - else - return !entry.is_named() && entry.get_id() == id_; -} - -//Returns resource_directory_entry by ID. If not found - throws an exception -const resource_directory_entry& resource_directory::entry_by_id(uint32_t id) const -{ - entry_list::const_iterator i = std::find_if(entries_.begin(), entries_.end(), id_entry_finder(id)); - if(i == entries_.end()) - throw pe_exception("Resource directory entry not found", pe_exception::resource_directory_entry_not_found); - - return *i; -} - -//Returns resource_directory_entry by name. If not found - throws an exception -const resource_directory_entry& resource_directory::entry_by_name(const std::wstring& name) const -{ - entry_list::const_iterator i = std::find_if(entries_.begin(), entries_.end(), name_entry_finder(name)); - if(i == entries_.end()) - throw pe_exception("Resource directory entry not found", pe_exception::resource_directory_entry_not_found); - - return *i; -} -} diff --git a/tools/pe_bliss/pe_resources.h b/tools/pe_bliss/pe_resources.h deleted file mode 100644 index 1eb6437563..0000000000 --- a/tools/pe_bliss/pe_resources.h +++ /dev/null @@ -1,245 +0,0 @@ -/*************************************************************************/ -/* Copyright (c) 2015 dx, http://kaimi.ru */ -/* */ -/* Permission is hereby granted, free of charge, to any person */ -/* obtaining a copy of this software and associated documentation */ -/* files (the "Software"), to deal in the Software without */ -/* restriction, including without limitation the rights to use, */ -/* copy, modify, merge, publish, distribute, sublicense, and/or */ -/* sell copies of the Software, and to permit persons to whom the */ -/* Software is furnished to do so, subject to the following conditions: */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#pragma once -#include <vector> -#include <string> -#include <set> -#include "pe_structures.h" -#include "pe_base.h" -#include "pe_directory.h" - -namespace pe_bliss -{ -//Class representing resource data entry -class resource_data_entry -{ -public: - //Default constructor - resource_data_entry(); - //Constructor from data - resource_data_entry(const std::string& data, uint32_t codepage); - - //Returns resource data codepage - uint32_t get_codepage() const; - //Returns resource data - const std::string& get_data() const; - -public: //These functions do not change everything inside image, they are used by PE class - //You can also use them to rebuild resource directory - - //Sets resource data codepage - void set_codepage(uint32_t codepage); - //Sets resource data - void set_data(const std::string& data); - -private: - uint32_t codepage_; //Resource data codepage - std::string data_; //Resource data -}; - -//Forward declaration -class resource_directory; - -//Class representing resource directory entry -class resource_directory_entry -{ -public: - //Default constructor - resource_directory_entry(); - //Copy constructor - resource_directory_entry(const resource_directory_entry& other); - //Copy assignment operator - resource_directory_entry& operator=(const resource_directory_entry& other); - - //Returns entry ID - uint32_t get_id() const; - //Returns entry name - const std::wstring& get_name() const; - //Returns true, if entry has name - //Returns false, if entry has ID - bool is_named() const; - - //Returns true, if entry includes resource_data_entry - //Returns false, if entry includes resource_directory - bool includes_data() const; - //Returns resource_directory if entry includes it, otherwise throws an exception - const resource_directory& get_resource_directory() const; - //Returns resource_data_entry if entry includes it, otherwise throws an exception - const resource_data_entry& get_data_entry() const; - - //Destructor - ~resource_directory_entry(); - -public: //These functions do not change everything inside image, they are used by PE class - //You can also use them to rebuild resource directory - - //Sets entry name - void set_name(const std::wstring& name); - //Sets entry ID - void set_id(uint32_t id); - - //Returns resource_directory if entry includes it, otherwise throws an exception - resource_directory& get_resource_directory(); - //Returns resource_data_entry if entry includes it, otherwise throws an exception - resource_data_entry& get_data_entry(); - - //Adds resource_data_entry - void add_data_entry(const resource_data_entry& entry); - //Adds resource_directory - void add_resource_directory(const resource_directory& dir); - -private: - //Destroys included data - void release(); - -private: - uint32_t id_; - std::wstring name_; - - union includes - { - //Default constructor - includes(); - - //We use pointers, we're doing manual copying here - class resource_data_entry* data_; - class resource_directory* dir_; //We use pointer, because structs include each other - }; - - includes ptr_; - - bool includes_data_, named_; -}; - -//Class representing resource directory -class resource_directory -{ -public: - typedef std::vector<resource_directory_entry> entry_list; - -public: - //Default constructor - resource_directory(); - //Constructor from data - explicit resource_directory(const pe_win::image_resource_directory& dir); - - //Returns characteristics of directory - uint32_t get_characteristics() const; - //Returns date and time stamp of directory - uint32_t get_timestamp() const; - //Returns number of named entries - uint32_t get_number_of_named_entries() const; - //Returns number of ID entries - uint32_t get_number_of_id_entries() const; - //Returns major version of directory - uint16_t get_major_version() const; - //Returns minor version of directory - uint16_t get_minor_version() const; - //Returns resource_directory_entry array - const entry_list& get_entry_list() const; - //Returns resource_directory_entry by ID. If not found - throws an exception - const resource_directory_entry& entry_by_id(uint32_t id) const; - //Returns resource_directory_entry by name. If not found - throws an exception - const resource_directory_entry& entry_by_name(const std::wstring& name) const; - -public: //These functions do not change everything inside image, they are used by PE class - //You can also use them to rebuild resource directory - - //Adds resource_directory_entry - void add_resource_directory_entry(const resource_directory_entry& entry); - //Clears resource_directory_entry array - void clear_resource_directory_entry_list(); - - //Sets characteristics of directory - void set_characteristics(uint32_t characteristics); - //Sets date and time stamp of directory - void set_timestamp(uint32_t timestamp); - //Sets number of named entries - void set_number_of_named_entries(uint32_t number); - //Sets number of ID entries - void set_number_of_id_entries(uint32_t number); - //Sets major version of directory - void set_major_version(uint16_t major_version); - //Sets minor version of directory - void get_minor_version(uint16_t minor_version); - - //Returns resource_directory_entry array - entry_list& get_entry_list(); - -private: - uint32_t characteristics_; - uint32_t timestamp_; - uint16_t major_version_, minor_version_; - uint32_t number_of_named_entries_, number_of_id_entries_; - entry_list entries_; - -public: //Finder helpers - //Finds resource_directory_entry by ID - struct id_entry_finder - { - public: - explicit id_entry_finder(uint32_t id); - bool operator()(const resource_directory_entry& entry) const; - - private: - uint32_t id_; - }; - - //Finds resource_directory_entry by name - struct name_entry_finder - { - public: - explicit name_entry_finder(const std::wstring& name); - bool operator()(const resource_directory_entry& entry) const; - - private: - std::wstring name_; - }; - - //Finds resource_directory_entry by name or ID (universal) - struct entry_finder - { - public: - explicit entry_finder(const std::wstring& name); - explicit entry_finder(uint32_t id); - bool operator()(const resource_directory_entry& entry) const; - - private: - std::wstring name_; - uint32_t id_; - bool named_; - }; -}; - -//Returns resources (root resource_directory) from PE file -const resource_directory get_resources(const pe_base& pe); - -//Resources rebuilder -//resource_directory - root resource directory -//resources_section - section where resource directory will be placed (must be attached to PE image) -//resource_directory is non-constant, because it will be sorted -//offset_from_section_start - offset from resources_section raw data start -//save_to_pe_headers - if true, new resource directory information will be saved to PE image headers -//auto_strip_last_section - if true and resources are placed in the last section, it will be automatically stripped -//number_of_id_entries and number_of_named_entries for resource directories are recalculated and not used -const image_directory rebuild_resources(pe_base& pe, resource_directory& info, section& resources_section, uint32_t offset_from_section_start = 0, bool save_to_pe_header = true, bool auto_strip_last_section = true); -} diff --git a/tools/pe_bliss/pe_rich_data.cpp b/tools/pe_bliss/pe_rich_data.cpp deleted file mode 100644 index e92f7ddc1b..0000000000 --- a/tools/pe_bliss/pe_rich_data.cpp +++ /dev/null @@ -1,152 +0,0 @@ -/*************************************************************************/ -/* Copyright (c) 2015 dx, http://kaimi.ru */ -/* */ -/* Permission is hereby granted, free of charge, to any person */ -/* obtaining a copy of this software and associated documentation */ -/* files (the "Software"), to deal in the Software without */ -/* restriction, including without limitation the rights to use, */ -/* copy, modify, merge, publish, distribute, sublicense, and/or */ -/* sell copies of the Software, and to permit persons to whom the */ -/* Software is furnished to do so, subject to the following conditions: */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#include "pe_rich_data.h" - -namespace pe_bliss -{ -//STUB OVERLAY -//Default constructor -rich_data::rich_data() - :number_(0), version_(0), times_(0) -{} - -//Who knows, what these fields mean... -uint32_t rich_data::get_number() const -{ - return number_; -} - -uint32_t rich_data::get_version() const -{ - return version_; -} - -uint32_t rich_data::get_times() const -{ - return times_; -} - -void rich_data::set_number(uint32_t number) -{ - number_ = number; -} - -void rich_data::set_version(uint32_t version) -{ - version_ = version; -} - -void rich_data::set_times(uint32_t times) -{ - times_ = times; -} - -//Returns MSVC rich data -const rich_data_list get_rich_data(const pe_base& pe) -{ - //Returned value - rich_data_list ret; - - const std::string& rich_overlay = pe.get_stub_overlay(); - - //If there's no rich overlay, return empty vector - if(rich_overlay.size() < sizeof(uint32_t)) - return ret; - - //True if rich data was found - bool found = false; - - //Rich overlay ID ("Rich" word) - static const uint32_t rich_overlay_id = 0x68636952; - - //Search for rich data overlay ID - const char* begin = &rich_overlay[0]; - const char* end = begin + rich_overlay.length(); - for(; begin != end; ++begin) - { - if(*reinterpret_cast<const uint32_t*>(begin) == rich_overlay_id) - { - found = true; //We've found it! - break; - } - } - - //If we found it - if(found) - { - //Check remaining length - if(static_cast<size_t>(end - begin) < sizeof(uint32_t)) - return ret; - - //The XOR key is after "Rich" word, we should get it - uint32_t xorkey = *reinterpret_cast<const uint32_t*>(begin + sizeof(uint32_t)); - - //True if rich data was found - found = false; - - //Second search for signature "DanS" - begin = &rich_overlay[0]; - for(; begin != end; ++begin) - { - if((*reinterpret_cast<const uint32_t*>(begin) ^ xorkey) == 0x536e6144) //"DanS" - { - found = true; - break; - } - } - - //If second signature is found - if(found) - { - begin += sizeof(uint32_t) * 3; - //List all rich data structures - while(begin < end) - { - begin += sizeof(uint32_t); - if(begin >= end) - break; - - //Check for rich overlay data end ("Rich" word reached) - if(*reinterpret_cast<const uint32_t*>(begin) == rich_overlay_id) - break; - - //Create rich_data structure - rich_data data; - data.set_number((*reinterpret_cast<const uint32_t*>(begin) ^ xorkey) >> 16); - data.set_version((*reinterpret_cast<const uint32_t*>(begin) ^ xorkey) & 0xFFFF); - - begin += sizeof(uint32_t); - if(begin >= end) - break; - - data.set_times(*reinterpret_cast<const uint32_t*>(begin) ^ xorkey); - - //Save rich data structure - ret.push_back(data); - } - } - } - - //Return rich data structures list - return ret; -} -} diff --git a/tools/pe_bliss/pe_rich_data.h b/tools/pe_bliss/pe_rich_data.h deleted file mode 100644 index 3e01d3c011..0000000000 --- a/tools/pe_bliss/pe_rich_data.h +++ /dev/null @@ -1,58 +0,0 @@ -/*************************************************************************/ -/* Copyright (c) 2015 dx, http://kaimi.ru */ -/* */ -/* Permission is hereby granted, free of charge, to any person */ -/* obtaining a copy of this software and associated documentation */ -/* files (the "Software"), to deal in the Software without */ -/* restriction, including without limitation the rights to use, */ -/* copy, modify, merge, publish, distribute, sublicense, and/or */ -/* sell copies of the Software, and to permit persons to whom the */ -/* Software is furnished to do so, subject to the following conditions: */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#pragma once -#include <vector> -#include "pe_structures.h" -#include "pe_base.h" - -namespace pe_bliss -{ -//Rich data overlay class of Microsoft Visual Studio -class rich_data -{ -public: - //Default constructor - rich_data(); - -public: //Getters - //Who knows, what these fields mean... - uint32_t get_number() const; - uint32_t get_version() const; - uint32_t get_times() const; - -public: //Setters, used by PE library only - void set_number(uint32_t number); - void set_version(uint32_t version); - void set_times(uint32_t times); - -private: - uint32_t number_; - uint32_t version_; - uint32_t times_; -}; - -//Rich data list typedef -typedef std::vector<rich_data> rich_data_list; - -//Returns a vector with rich data (stub overlay) -const rich_data_list get_rich_data(const pe_base& pe); -} diff --git a/tools/pe_bliss/pe_section.cpp b/tools/pe_bliss/pe_section.cpp deleted file mode 100644 index 72127e22e2..0000000000 --- a/tools/pe_bliss/pe_section.cpp +++ /dev/null @@ -1,303 +0,0 @@ -/*************************************************************************/ -/* Copyright (c) 2015 dx, http://kaimi.ru */ -/* */ -/* Permission is hereby granted, free of charge, to any person */ -/* obtaining a copy of this software and associated documentation */ -/* files (the "Software"), to deal in the Software without */ -/* restriction, including without limitation the rights to use, */ -/* copy, modify, merge, publish, distribute, sublicense, and/or */ -/* sell copies of the Software, and to permit persons to whom the */ -/* Software is furnished to do so, subject to the following conditions: */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#include <algorithm> -#include <string.h> -#include "utils.h" -#include "pe_section.h" - -namespace pe_bliss -{ -using namespace pe_win; - -//Section structure default constructor -section::section() - :old_size_(static_cast<size_t>(-1)) -{ - memset(&header_, 0, sizeof(image_section_header)); -} - -//Sets the name of section (8 characters maximum) -void section::set_name(const std::string& name) -{ - memset(header_.Name, 0, sizeof(header_.Name)); - memcpy(header_.Name, name.c_str(), std::min<size_t>(name.length(), sizeof(header_.Name))); -} - -//Returns section name -const std::string section::get_name() const -{ - char buf[9] = {0}; - memcpy(buf, header_.Name, 8); - return std::string(buf); -} - -//Set flag (attribute) of section -section& section::set_flag(uint32_t flag, bool setflag) -{ - if(setflag) - header_.Characteristics |= flag; - else - header_.Characteristics &= ~flag; - - return *this; -} - -//Sets "readable" attribute of section -section& section::readable(bool readable) -{ - return set_flag(image_scn_mem_read, readable); -} - -//Sets "writeable" attribute of section -section& section::writeable(bool writeable) -{ - return set_flag(image_scn_mem_write, writeable); -} - -//Sets "executable" attribute of section -section& section::executable(bool executable) -{ - return set_flag(image_scn_mem_execute, executable); -} - -//Sets "shared" attribute of section -section& section::shared(bool shared) -{ - return set_flag(image_scn_mem_shared, shared); -} - -//Sets "discardable" attribute of section -section& section::discardable(bool discardable) -{ - return set_flag(image_scn_mem_discardable, discardable); -} - -//Returns true if section is readable -bool section::readable() const -{ - return (header_.Characteristics & image_scn_mem_read) != 0; -} - -//Returns true if section is writeable -bool section::writeable() const -{ - return (header_.Characteristics & image_scn_mem_write) != 0; -} - -//Returns true if section is executable -bool section::executable() const -{ - return (header_.Characteristics & image_scn_mem_execute) != 0; -} - -bool section::shared() const -{ - return (header_.Characteristics & image_scn_mem_shared) != 0; -} - -bool section::discardable() const -{ - return (header_.Characteristics & image_scn_mem_discardable) != 0; -} - -//Returns true if section has no RAW data -bool section::empty() const -{ - if(old_size_ != static_cast<size_t>(-1)) //If virtual memory is mapped, check raw data length (old_size_) - return old_size_ == 0; - else - return raw_data_.empty(); -} - -//Returns raw section data from file image -std::string& section::get_raw_data() -{ - unmap_virtual(); - return raw_data_; -} - -//Sets raw section data from file image -void section::set_raw_data(const std::string& data) -{ - old_size_ = static_cast<size_t>(-1); - raw_data_ = data; -} - -//Returns raw section data from file image -const std::string& section::get_raw_data() const -{ - unmap_virtual(); - return raw_data_; -} - -//Returns mapped virtual section data -const std::string& section::get_virtual_data(uint32_t section_alignment) const -{ - map_virtual(section_alignment); - return raw_data_; -} - -//Returns mapped virtual section data -std::string& section::get_virtual_data(uint32_t section_alignment) -{ - map_virtual(section_alignment); - return raw_data_; -} - -//Maps virtual section data -void section::map_virtual(uint32_t section_alignment) const -{ - uint32_t aligned_virtual_size = get_aligned_virtual_size(section_alignment); - if(old_size_ == static_cast<size_t>(-1) && aligned_virtual_size && aligned_virtual_size > raw_data_.length()) - { - old_size_ = raw_data_.length(); - raw_data_.resize(aligned_virtual_size, 0); - } -} - -//Unmaps virtual section data -void section::unmap_virtual() const -{ - if(old_size_ != static_cast<size_t>(-1)) - { - raw_data_.resize(old_size_, 0); - old_size_ = static_cast<size_t>(-1); - } -} - -//Returns section virtual size -uint32_t section::get_virtual_size() const -{ - return header_.Misc.VirtualSize; -} - -//Returns section virtual address -uint32_t section::get_virtual_address() const -{ - return header_.VirtualAddress; -} - -//Returns size of section raw data -uint32_t section::get_size_of_raw_data() const -{ - return header_.SizeOfRawData; -} - -//Returns pointer to raw section data in PE file -uint32_t section::get_pointer_to_raw_data() const -{ - return header_.PointerToRawData; -} - -//Returns section characteristics -uint32_t section::get_characteristics() const -{ - return header_.Characteristics; -} - -//Returns raw image section header -const pe_win::image_section_header& section::get_raw_header() const -{ - return header_; -} - -//Returns raw image section header -pe_win::image_section_header& section::get_raw_header() -{ - return header_; -} - -//Calculates aligned virtual section size -uint32_t section::get_aligned_virtual_size(uint32_t section_alignment) const -{ - if(get_size_of_raw_data()) - { - if(!get_virtual_size()) - { - //If section virtual size is zero - //Set aligned virtual size of section as aligned raw size - return pe_utils::align_up(get_size_of_raw_data(), section_alignment); - } - } - - return pe_utils::align_up(get_virtual_size(), section_alignment); -} - -//Calculates aligned raw section size -uint32_t section::get_aligned_raw_size(uint32_t file_alignment) const -{ - if(get_size_of_raw_data()) - return pe_utils::align_up(get_size_of_raw_data(), file_alignment); - else - return 0; -} - -//Sets size of raw section data -void section::set_size_of_raw_data(uint32_t size_of_raw_data) -{ - header_.SizeOfRawData = size_of_raw_data; -} - -//Sets pointer to section raw data -void section::set_pointer_to_raw_data(uint32_t pointer_to_raw_data) -{ - header_.PointerToRawData = pointer_to_raw_data; -} - -//Sets section characteristics -void section::set_characteristics(uint32_t characteristics) -{ - header_.Characteristics = characteristics; -} - -//Sets section virtual size -void section::set_virtual_size(uint32_t virtual_size) -{ - header_.Misc.VirtualSize = virtual_size; -} - -//Sets section virtual address -void section::set_virtual_address(uint32_t virtual_address) -{ - header_.VirtualAddress = virtual_address; -} - -//Section by file offset finder helper (4gb max) -section_by_raw_offset::section_by_raw_offset(uint32_t offset) - :offset_(offset) -{} - -bool section_by_raw_offset::operator()(const section& s) const -{ - return (s.get_pointer_to_raw_data() <= offset_) - && (s.get_pointer_to_raw_data() + s.get_size_of_raw_data() > offset_); -} - -section_ptr_finder::section_ptr_finder(const section& s) - :s_(s) -{} - -bool section_ptr_finder::operator()(const section& s) const -{ - return &s == &s_; -} -} diff --git a/tools/pe_bliss/pe_section.h b/tools/pe_bliss/pe_section.h deleted file mode 100644 index 617ecebe26..0000000000 --- a/tools/pe_bliss/pe_section.h +++ /dev/null @@ -1,158 +0,0 @@ -/*************************************************************************/ -/* Copyright (c) 2015 dx, http://kaimi.ru */ -/* */ -/* Permission is hereby granted, free of charge, to any person */ -/* obtaining a copy of this software and associated documentation */ -/* files (the "Software"), to deal in the Software without */ -/* restriction, including without limitation the rights to use, */ -/* copy, modify, merge, publish, distribute, sublicense, and/or */ -/* sell copies of the Software, and to permit persons to whom the */ -/* Software is furnished to do so, subject to the following conditions: */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#pragma once -#include <string> -#include <vector> -#include "pe_structures.h" - -namespace pe_bliss -{ -//Enumeration of section data types, used in functions below -enum section_data_type -{ - section_data_raw, - section_data_virtual -}; - -//Class representing image section -class section -{ -public: - //Default constructor - section(); - - //Sets the name of section (stripped to 8 characters) - void set_name(const std::string& name); - - //Returns the name of section - const std::string get_name() const; - - //Changes attributes of section - section& readable(bool readable); - section& writeable(bool writeable); - section& executable(bool executable); - section& shared(bool shared); - section& discardable(bool discardable); - - //Returns attributes of section - bool readable() const; - bool writeable() const; - bool executable() const; - bool shared() const; - bool discardable() const; - - //Returns true if section has no RAW data - bool empty() const; - - //Returns raw section data from file image - std::string& get_raw_data(); - //Returns raw section data from file image - const std::string& get_raw_data() const; - //Returns mapped virtual section data - const std::string& get_virtual_data(uint32_t section_alignment) const; - //Returns mapped virtual section data - std::string& get_virtual_data(uint32_t section_alignment); - -public: //Header getters - //Returns section virtual size - uint32_t get_virtual_size() const; - //Returns section virtual address (RVA) - uint32_t get_virtual_address() const; - //Returns size of section raw data - uint32_t get_size_of_raw_data() const; - //Returns pointer to raw section data in PE file - uint32_t get_pointer_to_raw_data() const; - //Returns section characteristics - uint32_t get_characteristics() const; - - //Returns raw image section header - const pe_win::image_section_header& get_raw_header() const; - -public: //Aligned sizes calculation - //Calculates aligned virtual section size - uint32_t get_aligned_virtual_size(uint32_t section_alignment) const; - //Calculates aligned raw section size - uint32_t get_aligned_raw_size(uint32_t file_alignment) const; - -public: //Setters - //Sets size of raw section data - void set_size_of_raw_data(uint32_t size_of_raw_data); - //Sets pointer to section raw data - void set_pointer_to_raw_data(uint32_t pointer_to_raw_data); - //Sets section characteristics - void set_characteristics(uint32_t characteristics); - //Sets raw section data from file image - void set_raw_data(const std::string& data); - -public: //Setters, be careful - //Sets section virtual size (doesn't set internal aligned virtual size, changes only header value) - //Better use pe_base::set_section_virtual_size - void set_virtual_size(uint32_t virtual_size); - //Sets section virtual address - void set_virtual_address(uint32_t virtual_address); - //Returns raw image section header - pe_win::image_section_header& get_raw_header(); - -private: - //Section header - pe_win::image_section_header header_; - - //Maps virtual section data - void map_virtual(uint32_t section_alignment) const; - - //Unmaps virtual section data - void unmap_virtual() const; - - //Set flag (attribute) of section - section& set_flag(uint32_t flag, bool setflag); - - //Old size of section (stored after mapping of virtual section memory) - mutable std::size_t old_size_; - - //Section raw/virtual data - mutable std::string raw_data_; -}; - -//Section by file offset finder helper (4gb max) -struct section_by_raw_offset -{ -public: - explicit section_by_raw_offset(uint32_t offset); - bool operator()(const section& s) const; - -private: - uint32_t offset_; -}; - -//Helper: finder of section* in sections list -struct section_ptr_finder -{ -public: - explicit section_ptr_finder(const section& s); - bool operator()(const section& s) const; - -private: - const section& s_; -}; - -typedef std::vector<section> section_list; -} diff --git a/tools/pe_bliss/pe_structures.h b/tools/pe_bliss/pe_structures.h deleted file mode 100644 index efc99103b2..0000000000 --- a/tools/pe_bliss/pe_structures.h +++ /dev/null @@ -1,1028 +0,0 @@ -/*************************************************************************/ -/* Copyright (c) 2015 dx, http://kaimi.ru */ -/* */ -/* Permission is hereby granted, free of charge, to any person */ -/* obtaining a copy of this software and associated documentation */ -/* files (the "Software"), to deal in the Software without */ -/* restriction, including without limitation the rights to use, */ -/* copy, modify, merge, publish, distribute, sublicense, and/or */ -/* sell copies of the Software, and to permit persons to whom the */ -/* Software is furnished to do so, subject to the following conditions: */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#pragma once -#include <string> -#include <sstream> -#include "stdint_defs.h" -#if defined(_MSC_VER) or defined(__MINGW32__) -#define PE_BLISS_WINDOWS -#endif - -namespace pe_bliss -{ -//Enumeration of PE types -enum pe_type -{ - pe_type_32, - pe_type_64 -}; - -namespace pe_win -{ -const uint32_t image_numberof_directory_entries = 16; -const uint32_t image_nt_optional_hdr32_magic = 0x10b; -const uint32_t image_nt_optional_hdr64_magic = 0x20b; -const uint32_t image_resource_name_is_string = 0x80000000; -const uint32_t image_resource_data_is_directory = 0x80000000; - -const uint32_t image_dllcharacteristics_dynamic_base = 0x0040; // DLL can move. -const uint32_t image_dllcharacteristics_force_integrity = 0x0080; // Code Integrity Image -const uint32_t image_dllcharacteristics_nx_compat = 0x0100; // Image is NX compatible -const uint32_t image_dllcharacteristics_no_isolation = 0x0200; // Image understands isolation and doesn't want it -const uint32_t image_dllcharacteristics_no_seh = 0x0400; // Image does not use SEH. No SE handler may reside in this image -const uint32_t image_dllcharacteristics_no_bind = 0x0800; // Do not bind this image. -const uint32_t image_dllcharacteristics_wdm_driver = 0x2000; // Driver uses WDM model -const uint32_t image_dllcharacteristics_terminal_server_aware = 0x8000; - -const uint32_t image_sizeof_file_header = 20; - -const uint32_t image_file_relocs_stripped = 0x0001; // Relocation info stripped from file. -const uint32_t image_file_executable_image = 0x0002; // File is executable (i.e. no unresolved externel references). -const uint32_t image_file_line_nums_stripped = 0x0004; // Line nunbers stripped from file. -const uint32_t image_file_local_syms_stripped = 0x0008; // Local symbols stripped from file. -const uint32_t image_file_aggresive_ws_trim = 0x0010; // Agressively trim working set -const uint32_t image_file_large_address_aware = 0x0020; // App can handle >2gb addresses -const uint32_t image_file_bytes_reversed_lo = 0x0080; // Bytes of machine word are reversed. -const uint32_t image_file_32bit_machine = 0x0100; // 32 bit word machine. -const uint32_t image_file_debug_stripped = 0x0200; // Debugging info stripped from file in .DBG file -const uint32_t image_file_removable_run_from_swap = 0x0400; // If Image is on removable media, copy and run from the swap file. -const uint32_t image_file_net_run_from_swap = 0x0800; // If Image is on Net, copy and run from the swap file. -const uint32_t image_file_system = 0x1000; // System File. -const uint32_t image_file_dll = 0x2000; // File is a DLL. -const uint32_t image_file_up_system_only = 0x4000; // File should only be run on a UP machine -const uint32_t image_file_bytes_reversed_hi = 0x8000; // Bytes of machine word are reversed. - -const uint32_t image_scn_lnk_nreloc_ovfl = 0x01000000; // Section contains extended relocations. -const uint32_t image_scn_mem_discardable = 0x02000000; // Section can be discarded. -const uint32_t image_scn_mem_not_cached = 0x04000000; // Section is not cachable. -const uint32_t image_scn_mem_not_paged = 0x08000000; // Section is not pageable. -const uint32_t image_scn_mem_shared = 0x10000000; // Section is shareable. -const uint32_t image_scn_mem_execute = 0x20000000; // Section is executable. -const uint32_t image_scn_mem_read = 0x40000000; // Section is readable. -const uint32_t image_scn_mem_write = 0x80000000; // Section is writeable. - -const uint32_t image_scn_cnt_code = 0x00000020; // Section contains code. -const uint32_t image_scn_cnt_initialized_data = 0x00000040; // Section contains initialized data. -const uint32_t image_scn_cnt_uninitialized_data = 0x00000080; // Section contains uninitialized data. - -//Directory Entries -const uint32_t image_directory_entry_export = 0; // Export Directory -const uint32_t image_directory_entry_import = 1; // Import Directory -const uint32_t image_directory_entry_resource = 2; // Resource Directory -const uint32_t image_directory_entry_exception = 3; // Exception Directory -const uint32_t image_directory_entry_security = 4; // Security Directory -const uint32_t image_directory_entry_basereloc = 5; // Base Relocation Table -const uint32_t image_directory_entry_debug = 6; // Debug Directory -const uint32_t image_directory_entry_architecture = 7; // Architecture Specific Data -const uint32_t image_directory_entry_globalptr = 8; // RVA of GP -const uint32_t image_directory_entry_tls = 9; // TLS Directory -const uint32_t image_directory_entry_load_config = 10; // Load Configuration Directory -const uint32_t image_directory_entry_bound_import = 11; // Bound Import Directory in headers -const uint32_t image_directory_entry_iat = 12; // Import Address Table -const uint32_t image_directory_entry_delay_import = 13; // Delay Load Import Descriptors -const uint32_t image_directory_entry_com_descriptor = 14; // COM Runtime descriptor - -//Subsystem Values -const uint32_t image_subsystem_unknown = 0; // Unknown subsystem. -const uint32_t image_subsystem_native = 1; // Image doesn't require a subsystem. -const uint32_t image_subsystem_windows_gui = 2; // Image runs in the Windows GUI subsystem. -const uint32_t image_subsystem_windows_cui = 3; // Image runs in the Windows character subsystem. -const uint32_t image_subsystem_os2_cui = 5; // image runs in the OS/2 character subsystem. -const uint32_t image_subsystem_posix_cui = 7; // image runs in the Posix character subsystem. -const uint32_t image_subsystem_native_windows = 8; // image is a native Win9x driver. -const uint32_t image_subsystem_windows_ce_gui = 9; // Image runs in the Windows CE subsystem. -const uint32_t image_subsystem_efi_application = 10; // -const uint32_t image_subsystem_efi_boot_service_driver = 11; // -const uint32_t image_subsystem_efi_runtime_driver = 12; // -const uint32_t image_subsystem_efi_rom = 13; -const uint32_t image_subsystem_xbox = 14; -const uint32_t image_subsystem_windows_boot_application = 16; - -//Imports -const uint64_t image_ordinal_flag64 = 0x8000000000000000ull; -const uint32_t image_ordinal_flag32 = 0x80000000; - -//Based relocation types -const uint32_t image_rel_based_absolute = 0; -const uint32_t image_rel_based_high = 1; -const uint32_t image_rel_based_low = 2; -const uint32_t image_rel_based_highlow = 3; -const uint32_t image_rel_based_highadj = 4; -const uint32_t image_rel_based_mips_jmpaddr = 5; -const uint32_t image_rel_based_mips_jmpaddr16 = 9; -const uint32_t image_rel_based_ia64_imm64 = 9; -const uint32_t image_rel_based_dir64 = 10; - -//Exception directory -//The function has an exception handler that should be called when looking for functions that need to examine exceptions -const uint32_t unw_flag_ehandler = 0x01; -//The function has a termination handler that should be called when unwinding an exception -const uint32_t unw_flag_uhandler = 0x02; -//This unwind info structure is not the primary one for the procedure. -//Instead, the chained unwind info entry is the contents of a previous RUNTIME_FUNCTION entry. -//If this flag is set, then the UNW_FLAG_EHANDLER and UNW_FLAG_UHANDLER flags must be cleared. -//Also, the frame register and fixed-stack allocation fields must have the same values as in the primary unwind info -const uint32_t unw_flag_chaininfo = 0x04; - -//Debug -const uint32_t image_debug_misc_exename = 1; -const uint32_t image_debug_type_unknown = 0; -const uint32_t image_debug_type_coff = 1; -const uint32_t image_debug_type_codeview = 2; -const uint32_t image_debug_type_fpo = 3; -const uint32_t image_debug_type_misc = 4; -const uint32_t image_debug_type_exception = 5; -const uint32_t image_debug_type_fixup = 6; -const uint32_t image_debug_type_omap_to_src = 7; -const uint32_t image_debug_type_omap_from_src = 8; -const uint32_t image_debug_type_borland = 9; -const uint32_t image_debug_type_reserved10 = 10; -const uint32_t image_debug_type_clsid = 11; - - -//Storage classes -const uint32_t image_sym_class_end_of_function = static_cast<uint8_t>(-1); -const uint32_t image_sym_class_null = 0x0000; -const uint32_t image_sym_class_automatic = 0x0001; -const uint32_t image_sym_class_external = 0x0002; -const uint32_t image_sym_class_static = 0x0003; -const uint32_t image_sym_class_register = 0x0004; -const uint32_t image_sym_class_external_def = 0x0005; -const uint32_t image_sym_class_label = 0x0006; -const uint32_t image_sym_class_undefined_label = 0x0007; -const uint32_t image_sym_class_member_of_struct = 0x0008; -const uint32_t image_sym_class_argument = 0x0009; -const uint32_t image_sym_class_struct_tag = 0x000a; -const uint32_t image_sym_class_member_of_union = 0x000b; -const uint32_t image_sym_class_union_tag = 0x000c; -const uint32_t image_sym_class_type_definition = 0x000d; -const uint32_t image_sym_class_undefined_static = 0x000e; -const uint32_t image_sym_class_enum_tag = 0x000f; -const uint32_t image_sym_class_member_of_enum = 0x0010; -const uint32_t image_sym_class_register_param = 0x0011; -const uint32_t image_sym_class_bit_field = 0x0012; - -const uint32_t image_sym_class_far_external = 0x0044; - -const uint32_t image_sym_class_block = 0x0064; -const uint32_t image_sym_class_function = 0x0065; -const uint32_t image_sym_class_end_of_struct = 0x0066; -const uint32_t image_sym_class_file = 0x0067; - -const uint32_t image_sym_class_section = 0x0068; -const uint32_t image_sym_class_weak_external = 0x0069; - -const uint32_t image_sym_class_clr_token = 0x006b; - -//type packing constants -const uint32_t n_btmask = 0x000f; -const uint32_t n_tmask = 0x0030; -const uint32_t n_tmask1 = 0x00c0; -const uint32_t n_tmask2 = 0x00f0; -const uint32_t n_btshft = 4; -const uint32_t n_tshift = 2; - -//Type (derived) values. -const uint32_t image_sym_dtype_null = 0; // no derived type. -const uint32_t image_sym_dtype_pointer = 1; // pointer. -const uint32_t image_sym_dtype_function = 2; // function. -const uint32_t image_sym_dtype_array = 3; // array. - -// Is x a function? -//TODO -#ifndef ISFCN -#define ISFCN(x) (((x) & n_tmask) == (image_sym_dtype_function << n_btshft)) -#endif - -//Version info -const uint32_t vs_ffi_fileflagsmask = 0x0000003FL; - -const uint32_t vs_ffi_signature = 0xFEEF04BDL; -const uint32_t vs_ffi_strucversion = 0x00010000L; - -/* ----- VS_VERSION.dwFileFlags ----- */ -const uint32_t vs_ff_debug = 0x00000001L; -const uint32_t vs_ff_prerelease = 0x00000002L; -const uint32_t vs_ff_patched = 0x00000004L; -const uint32_t vs_ff_privatebuild = 0x00000008L; -const uint32_t vs_ff_infoinferred = 0x00000010L; -const uint32_t vs_ff_specialbuild = 0x00000020L; - -/* ----- VS_VERSION.dwFileOS ----- */ -const uint32_t vos_unknown = 0x00000000L; -const uint32_t vos_dos = 0x00010000L; -const uint32_t vos_os216 = 0x00020000L; -const uint32_t vos_os232 = 0x00030000L; -const uint32_t vos_nt = 0x00040000L; -const uint32_t vos_wince = 0x00050000L; - -const uint32_t vos__base = 0x00000000L; -const uint32_t vos__windows16 = 0x00000001L; -const uint32_t vos__pm16 = 0x00000002L; -const uint32_t vos__pm32 = 0x00000003L; -const uint32_t vos__windows32 = 0x00000004L; - -const uint32_t vos_dos_windows16 = 0x00010001L; -const uint32_t vos_dos_windows32 = 0x00010004L; -const uint32_t vos_os216_pm16 = 0x00020002L; -const uint32_t vos_os232_pm32 = 0x00030003L; -const uint32_t vos_nt_windows32 = 0x00040004L; - -/* ----- VS_VERSION.dwFileType ----- */ -const uint32_t vft_unknown = 0x00000000L; -const uint32_t vft_app = 0x00000001L; -const uint32_t vft_dll = 0x00000002L; -const uint32_t vft_drv = 0x00000003L; -const uint32_t vft_font = 0x00000004L; -const uint32_t vft_vxd = 0x00000005L; -const uint32_t vft_static_lib = 0x00000007L; - -const uint32_t message_resource_unicode = 0x0001; - -#pragma pack(push, 1) - -//Windows GUID structure -struct guid -{ - uint32_t Data1; - uint16_t Data2; - uint16_t Data3; - uint8_t Data4[8]; -}; - -//DOS .EXE header -struct image_dos_header -{ - uint16_t e_magic; // Magic number - uint16_t e_cblp; // Bytes on last page of file - uint16_t e_cp; // Pages in file - uint16_t e_crlc; // Relocations - uint16_t e_cparhdr; // Size of header in paragraphs - uint16_t e_minalloc; // Minimum extra paragraphs needed - uint16_t e_maxalloc; // Maximum extra paragraphs needed - uint16_t e_ss; // Initial (relative) SS value - uint16_t e_sp; // Initial SP value - uint16_t e_csum; // Checksum - uint16_t e_ip; // Initial IP value - uint16_t e_cs; // Initial (relative) CS value - uint16_t e_lfarlc; // File address of relocation table - uint16_t e_ovno; // Overlay number - uint16_t e_res[4]; // Reserved words - uint16_t e_oemid; // OEM identifier (for e_oeminfo) - uint16_t e_oeminfo; // OEM information; e_oemid specific - uint16_t e_res2[10]; // Reserved words - int32_t e_lfanew; // File address of new exe header -}; - -//Directory format -struct image_data_directory -{ - uint32_t VirtualAddress; - uint32_t Size; -}; - -//Optional header format -struct image_optional_header32 -{ - //Standard fields - uint16_t Magic; - uint8_t MajorLinkerVersion; - uint8_t MinorLinkerVersion; - uint32_t SizeOfCode; - uint32_t SizeOfInitializedData; - uint32_t SizeOfUninitializedData; - uint32_t AddressOfEntryPoint; - uint32_t BaseOfCode; - uint32_t BaseOfData; - - //NT additional fields - uint32_t ImageBase; - uint32_t SectionAlignment; - uint32_t FileAlignment; - uint16_t MajorOperatingSystemVersion; - uint16_t MinorOperatingSystemVersion; - uint16_t MajorImageVersion; - uint16_t MinorImageVersion; - uint16_t MajorSubsystemVersion; - uint16_t MinorSubsystemVersion; - uint32_t Win32VersionValue; - uint32_t SizeOfImage; - uint32_t SizeOfHeaders; - uint32_t CheckSum; - uint16_t Subsystem; - uint16_t DllCharacteristics; - uint32_t SizeOfStackReserve; - uint32_t SizeOfStackCommit; - uint32_t SizeOfHeapReserve; - uint32_t SizeOfHeapCommit; - uint32_t LoaderFlags; - uint32_t NumberOfRvaAndSizes; - image_data_directory DataDirectory[image_numberof_directory_entries]; -}; - -struct image_optional_header64 -{ - uint16_t Magic; - uint8_t MajorLinkerVersion; - uint8_t MinorLinkerVersion; - uint32_t SizeOfCode; - uint32_t SizeOfInitializedData; - uint32_t SizeOfUninitializedData; - uint32_t AddressOfEntryPoint; - uint32_t BaseOfCode; - uint64_t ImageBase; - uint32_t SectionAlignment; - uint32_t FileAlignment; - uint16_t MajorOperatingSystemVersion; - uint16_t MinorOperatingSystemVersion; - uint16_t MajorImageVersion; - uint16_t MinorImageVersion; - uint16_t MajorSubsystemVersion; - uint16_t MinorSubsystemVersion; - uint32_t Win32VersionValue; - uint32_t SizeOfImage; - uint32_t SizeOfHeaders; - uint32_t CheckSum; - uint16_t Subsystem; - uint16_t DllCharacteristics; - uint64_t SizeOfStackReserve; - uint64_t SizeOfStackCommit; - uint64_t SizeOfHeapReserve; - uint64_t SizeOfHeapCommit; - uint32_t LoaderFlags; - uint32_t NumberOfRvaAndSizes; - image_data_directory DataDirectory[image_numberof_directory_entries]; -}; - -struct image_file_header -{ - uint16_t Machine; - uint16_t NumberOfSections; - uint32_t TimeDateStamp; - uint32_t PointerToSymbolTable; - uint32_t NumberOfSymbols; - uint16_t SizeOfOptionalHeader; - uint16_t Characteristics; -}; - -struct image_nt_headers64 -{ - uint32_t Signature; - image_file_header FileHeader; - image_optional_header64 OptionalHeader; -}; - -struct image_nt_headers32 -{ - uint32_t Signature; - image_file_header FileHeader; - image_optional_header32 OptionalHeader; -}; - -//Section header format -struct image_section_header -{ - uint8_t Name[8]; - union - { - uint32_t PhysicalAddress; - uint32_t VirtualSize; - } Misc; - - uint32_t VirtualAddress; - uint32_t SizeOfRawData; - uint32_t PointerToRawData; - uint32_t PointerToRelocations; - uint32_t PointerToLinenumbers; - uint16_t NumberOfRelocations; - uint16_t NumberOfLinenumbers; - uint32_t Characteristics; -}; - - -/// RESOURCES /// -struct image_resource_directory -{ - uint32_t Characteristics; - uint32_t TimeDateStamp; - uint16_t MajorVersion; - uint16_t MinorVersion; - uint16_t NumberOfNamedEntries; - uint16_t NumberOfIdEntries; - // IMAGE_RESOURCE_DIRECTORY_ENTRY DirectoryEntries[]; -}; - -struct vs_fixedfileinfo -{ - uint32_t dwSignature; /* e.g. 0xfeef04bd */ - uint32_t dwStrucVersion; /* e.g. 0x00000042 = "0.42" */ - uint32_t dwFileVersionMS; /* e.g. 0x00030075 = "3.75" */ - uint32_t dwFileVersionLS; /* e.g. 0x00000031 = "0.31" */ - uint32_t dwProductVersionMS; /* e.g. 0x00030010 = "3.10" */ - uint32_t dwProductVersionLS; /* e.g. 0x00000031 = "0.31" */ - uint32_t dwFileFlagsMask; /* = 0x3F for version "0.42" */ - uint32_t dwFileFlags; /* e.g. VFF_DEBUG | VFF_PRERELEASE */ - uint32_t dwFileOS; /* e.g. VOS_DOS_WINDOWS16 */ - uint32_t dwFileType; /* e.g. VFT_DRIVER */ - uint32_t dwFileSubtype; /* e.g. VFT2_DRV_KEYBOARD */ - uint32_t dwFileDateMS; /* e.g. 0 */ - uint32_t dwFileDateLS; /* e.g. 0 */ -}; - -struct bitmapinfoheader -{ - uint32_t biSize; - int32_t biWidth; - int32_t biHeight; - uint16_t biPlanes; - uint16_t biBitCount; - uint32_t biCompression; - uint32_t biSizeImage; - int32_t biXPelsPerMeter; - int32_t biYPelsPerMeter; - uint32_t biClrUsed; - uint32_t biClrImportant; -}; - -struct message_resource_entry -{ - uint16_t Length; - uint16_t Flags; - uint8_t Text[1]; -}; - -struct message_resource_block -{ - uint32_t LowId; - uint32_t HighId; - uint32_t OffsetToEntries; -}; - -struct message_resource_data -{ - uint32_t NumberOfBlocks; - message_resource_block Blocks[1]; -}; - -struct image_resource_directory_entry -{ - union - { - struct - { - uint32_t NameOffset:31; - uint32_t NameIsString:1; - }; - uint32_t Name; - uint16_t Id; - }; - - union - { - uint32_t OffsetToData; - struct - { - uint32_t OffsetToDirectory:31; - uint32_t DataIsDirectory:1; - }; - }; -}; - -struct image_resource_data_entry -{ - uint32_t OffsetToData; - uint32_t Size; - uint32_t CodePage; - uint32_t Reserved; -}; - -#pragma pack(push, 2) -struct bitmapfileheader -{ - uint16_t bfType; - uint32_t bfSize; - uint16_t bfReserved1; - uint16_t bfReserved2; - uint32_t bfOffBits; -}; -#pragma pack(pop) - - - -//Structure representing ICON file header -struct ico_header -{ - uint16_t Reserved; - uint16_t Type; //1 - uint16_t Count; //Count of icons included in icon group -}; - -//Structure that is stored in icon group directory in PE resources -struct icon_group -{ - uint8_t Width; - uint8_t Height; - uint8_t ColorCount; - uint8_t Reserved; - uint16_t Planes; - uint16_t BitCount; - uint32_t SizeInBytes; - uint16_t Number; //Represents resource ID in PE icon list -}; - -//Structure representing ICON directory entry inside ICON file -struct icondirentry -{ - uint8_t Width; - uint8_t Height; - uint8_t ColorCount; - uint8_t Reserved; - uint16_t Planes; - uint16_t BitCount; - uint32_t SizeInBytes; - uint32_t ImageOffset; //Offset from start of header to the image -}; - -//Structure representing CURSOR file header -struct cursor_header -{ - uint16_t Reserved; - uint16_t Type; //2 - uint16_t Count; //Count of cursors included in cursor group -}; - -struct cursor_group -{ - uint16_t Width; - uint16_t Height; //Divide by 2 to get the actual height. - uint16_t Planes; - uint16_t BitCount; - uint32_t SizeInBytes; - uint16_t Number; //Represents resource ID in PE icon list -}; - -//Structure representing CURSOR directory entry inside CURSOR file -struct cursordirentry -{ - uint8_t Width; //Set to CURSOR_GROUP::Height/2. - uint8_t Height; - uint8_t ColorCount; - uint8_t Reserved; - uint16_t HotspotX; - uint16_t HotspotY; - uint32_t SizeInBytes; - uint32_t ImageOffset; //Offset from start of header to the image -}; - -//Structure representing BLOCK in version info resource -struct version_info_block //(always aligned on 32-bit (DWORD) boundary) -{ - uint16_t Length; //Length of this block (doesn't include padding) - uint16_t ValueLength; //Value length (if any) - uint16_t Type; //Value type (0 = binary, 1 = text) - uint16_t Key[1]; //Value name (block key) (always NULL terminated) - - ////////// - //WORD padding1[]; //Padding, if any (ALIGNMENT) - //xxxxx Value[]; //Value data, if any (*ALIGNED*) - //WORD padding2[]; //Padding, if any (ALIGNMENT) - //xxxxx Child[]; //Child block(s), if any (*ALIGNED*) - ////////// -}; - - -/// IMPORTS /// -#pragma pack(push, 8) -struct image_thunk_data64 -{ - union - { - uint64_t ForwarderString; // PBYTE - uint64_t Function; // PDWORD - uint64_t Ordinal; - uint64_t AddressOfData; // PIMAGE_IMPORT_BY_NAME - } u1; -}; -#pragma pack(pop) - -struct image_thunk_data32 -{ - union - { - uint32_t ForwarderString; // PBYTE - uint32_t Function; // PDWORD - uint32_t Ordinal; - uint32_t AddressOfData; // PIMAGE_IMPORT_BY_NAME - } u1; -}; - -struct image_import_descriptor -{ - union - { - uint32_t Characteristics; // 0 for terminating null import descriptor - uint32_t OriginalFirstThunk; // RVA to original unbound IAT (PIMAGE_THUNK_DATA) - }; - - uint32_t TimeDateStamp; // 0 if not bound, - // -1 if bound, and real date\time stamp - // in IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT (new BIND) - // O.W. date/time stamp of DLL bound to (Old BIND) - - uint32_t ForwarderChain; // -1 if no forwarders - uint32_t Name; - uint32_t FirstThunk; // RVA to IAT (if bound this IAT has actual addresses) -}; - - -/// TLS /// -struct image_tls_directory64 -{ - uint64_t StartAddressOfRawData; - uint64_t EndAddressOfRawData; - uint64_t AddressOfIndex; // PDWORD - uint64_t AddressOfCallBacks; // PIMAGE_TLS_CALLBACK *; - uint32_t SizeOfZeroFill; - uint32_t Characteristics; -}; - -struct image_tls_directory32 -{ - uint32_t StartAddressOfRawData; - uint32_t EndAddressOfRawData; - uint32_t AddressOfIndex; // PDWORD - uint32_t AddressOfCallBacks; // PIMAGE_TLS_CALLBACK * - uint32_t SizeOfZeroFill; - uint32_t Characteristics; -}; - - -/// Export Format /// -struct image_export_directory -{ - uint32_t Characteristics; - uint32_t TimeDateStamp; - uint16_t MajorVersion; - uint16_t MinorVersion; - uint32_t Name; - uint32_t Base; - uint32_t NumberOfFunctions; - uint32_t NumberOfNames; - uint32_t AddressOfFunctions; // RVA from base of image - uint32_t AddressOfNames; // RVA from base of image - uint32_t AddressOfNameOrdinals; // RVA from base of image -}; - - -/// Based relocation format /// -struct image_base_relocation -{ - uint32_t VirtualAddress; - uint32_t SizeOfBlock; - // uint16_t TypeOffset[1]; -}; - - -/// New format import descriptors pointed to by DataDirectory[ IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT ] /// -struct image_bound_import_descriptor -{ - uint32_t TimeDateStamp; - uint16_t OffsetModuleName; - uint16_t NumberOfModuleForwarderRefs; - // Array of zero or more IMAGE_BOUND_FORWARDER_REF follows -}; - -struct image_bound_forwarder_ref -{ - uint32_t TimeDateStamp; - uint16_t OffsetModuleName; - uint16_t Reserved; -}; - - -/// Exception directory /// -struct image_runtime_function_entry -{ - uint32_t BeginAddress; - uint32_t EndAddress; - uint32_t UnwindInfoAddress; -}; - -enum unwind_op_codes -{ - uwop_push_nonvol = 0, /* info == register number */ - uwop_alloc_large, /* no info, alloc size in next 2 slots */ - uwop_alloc_small, /* info == size of allocation / 8 - 1 */ - uwop_set_fpreg, /* no info, FP = RSP + UNWIND_INFO.FPRegOffset*16 */ - uwop_save_nonvol, /* info == register number, offset in next slot */ - uwop_save_nonvol_far, /* info == register number, offset in next 2 slots */ - uwop_save_xmm128, /* info == XMM reg number, offset in next slot */ - uwop_save_xmm128_far, /* info == XMM reg number, offset in next 2 slots */ - uwop_push_machframe /* info == 0: no error-code, 1: error-code */ -}; - -union unwind_code -{ - struct s - { - uint8_t CodeOffset; - uint8_t UnwindOp : 4; - uint8_t OpInfo : 4; - }; - - uint16_t FrameOffset; -}; - -struct unwind_info -{ - uint8_t Version : 3; - uint8_t Flags : 5; - uint8_t SizeOfProlog; - uint8_t CountOfCodes; - uint8_t FrameRegister : 4; - uint8_t FrameOffset : 4; - unwind_code UnwindCode[1]; - /* unwind_code MoreUnwindCode[((CountOfCodes + 1) & ~1) - 1]; - * union { - * OPTIONAL ULONG ExceptionHandler; - * OPTIONAL ULONG FunctionEntry; - * }; - * OPTIONAL ULONG ExceptionData[]; */ -}; - - - -/// Debug /// -struct image_debug_misc -{ - uint32_t DataType; // type of misc data, see defines - uint32_t Length; // total length of record, rounded to four - // byte multiple. - uint8_t Unicode; // TRUE if data is unicode string - uint8_t Reserved[3]; - uint8_t Data[1]; // Actual data -}; - -struct image_coff_symbols_header -{ - uint32_t NumberOfSymbols; - uint32_t LvaToFirstSymbol; - uint32_t NumberOfLinenumbers; - uint32_t LvaToFirstLinenumber; - uint32_t RvaToFirstByteOfCode; - uint32_t RvaToLastByteOfCode; - uint32_t RvaToFirstByteOfData; - uint32_t RvaToLastByteOfData; -}; - -struct image_debug_directory -{ - uint32_t Characteristics; - uint32_t TimeDateStamp; - uint16_t MajorVersion; - uint16_t MinorVersion; - uint32_t Type; - uint32_t SizeOfData; - uint32_t AddressOfRawData; - uint32_t PointerToRawData; -}; - - -#pragma pack(push, 2) -struct image_symbol -{ - union - { - uint8_t ShortName[8]; - struct - { - uint32_t Short; // if 0, use LongName - uint32_t Long; // offset into string table - } Name; - uint32_t LongName[2]; // PBYTE [2] - } N; - uint32_t Value; - int16_t SectionNumber; - uint16_t Type; - uint8_t StorageClass; - uint8_t NumberOfAuxSymbols; -}; -#pragma pack(pop) - -//CodeView Debug OMF signature. The signature at the end of the file is -//a negative offset from the end of the file to another signature. At -//the negative offset (base address) is another signature whose filepos -//field points to the first OMFDirHeader in a chain of directories. -//The NB05 signature is used by the link utility to indicated a completely -//unpacked file. The NB06 signature is used by ilink to indicate that the -//executable has had CodeView information from an incremental link appended -//to the executable. The NB08 signature is used by cvpack to indicate that -//the CodeView Debug OMF has been packed. CodeView will only process -//executables with the NB08 signature. -struct OMFSignature -{ - char Signature[4]; // "NBxx" - uint32_t filepos; // offset in file -}; - -struct CV_INFO_PDB20 -{ - OMFSignature CvHeader; - uint32_t Signature; - uint32_t Age; - uint8_t PdbFileName[1]; -}; - -struct CV_INFO_PDB70 -{ - uint32_t CvSignature; - guid Signature; - uint32_t Age; - uint8_t PdbFileName[1]; -}; - -// directory information structure -// This structure contains the information describing the directory. -// It is pointed to by the signature at the base address or the directory -// link field of a preceeding directory. The directory entries immediately -// follow this structure. -struct OMFDirHeader -{ - uint16_t cbDirHeader; // length of this structure - uint16_t cbDirEntry; // number of bytes in each directory entry - uint32_t cDir; // number of directorie entries - int32_t lfoNextDir; // offset from base of next directory - uint32_t flags; // status flags -}; - -// directory structure -// The data in this structure is used to reference the data for each -// subsection of the CodeView Debug OMF information. Tables that are -// not associated with a specific module will have a module index of -// oxffff. These tables are the global types table, the global symbol -// table, the global public table and the library table. -struct OMFDirEntry -{ - uint16_t SubSection; // subsection type (sst...) - uint16_t iMod; // module index - int32_t lfo; // large file offset of subsection - uint32_t cb; // number of bytes in subsection -}; - - -/// CLR 2.0 header structure /// -struct image_cor20_header -{ - //Header versioning - uint32_t cb; - uint16_t MajorRuntimeVersion; - uint16_t MinorRuntimeVersion; - - // Symbol table and startup information - image_data_directory MetaData; - uint32_t Flags; - - // If COMIMAGE_FLAGS_NATIVE_ENTRYPOINT is not set, EntryPointToken represents a managed entrypoint. - // If COMIMAGE_FLAGS_NATIVE_ENTRYPOINT is set, EntryPointRVA represents an RVA to a native entrypoint. - union - { - uint32_t EntryPointToken; - uint32_t EntryPointRVA; - }; - - // Binding information - image_data_directory Resources; - image_data_directory StrongNameSignature; - - // Regular fixup and binding information - image_data_directory CodeManagerTable; - image_data_directory VTableFixups; - image_data_directory ExportAddressTableJumps; - - // Precompiled image info (internal use only - set to zero) - image_data_directory ManagedNativeHeader; -}; - -enum replaces_cor_hdr_numeric_defines -{ - // COM+ Header entry point flags. - comimage_flags_ilonly =0x00000001, - comimage_flags_32bitrequired =0x00000002, - comimage_flags_il_library =0x00000004, - comimage_flags_strongnamesigned =0x00000008, - comimage_flags_native_entrypoint =0x00000010, - comimage_flags_trackdebugdata =0x00010000, - - // Version flags for image. - cor_version_major_v2 =2, - cor_version_major =cor_version_major_v2, - cor_version_minor =0, - cor_deleted_name_length =8, - cor_vtablegap_name_length =8, - - // Maximum size of a NativeType descriptor. - native_type_max_cb =1, - cor_ilmethod_sect_small_max_datasize=0xff, - - // #defines for the MIH FLAGS - image_cor_mih_methodrva =0x01, - image_cor_mih_ehrva =0x02, - image_cor_mih_basicblock =0x08, - - // V-table constants - cor_vtable_32bit =0x01, // V-table slots are 32-bits in size. - cor_vtable_64bit =0x02, // V-table slots are 64-bits in size. - cor_vtable_from_unmanaged =0x04, // If set, transition from unmanaged. - cor_vtable_from_unmanaged_retain_appdomain =0x08, // If set, transition from unmanaged with keeping the current appdomain. - cor_vtable_call_most_derived =0x10, // Call most derived method described by - - // EATJ constants - image_cor_eatj_thunk_size =32, // Size of a jump thunk reserved range. - - // Max name lengths - //@todo: Change to unlimited name lengths. - max_class_name =1024, - max_package_name =1024 -}; - -/// Load Configuration Directory Entry /// -struct image_load_config_directory32 -{ - uint32_t Size; - uint32_t TimeDateStamp; - uint16_t MajorVersion; - uint16_t MinorVersion; - uint32_t GlobalFlagsClear; - uint32_t GlobalFlagsSet; - uint32_t CriticalSectionDefaultTimeout; - uint32_t DeCommitFreeBlockThreshold; - uint32_t DeCommitTotalFreeThreshold; - uint32_t LockPrefixTable; // VA - uint32_t MaximumAllocationSize; - uint32_t VirtualMemoryThreshold; - uint32_t ProcessHeapFlags; - uint32_t ProcessAffinityMask; - uint16_t CSDVersion; - uint16_t Reserved1; - uint32_t EditList; // VA - uint32_t SecurityCookie; // VA - uint32_t SEHandlerTable; // VA - uint32_t SEHandlerCount; -}; - -struct image_load_config_directory64 -{ - uint32_t Size; - uint32_t TimeDateStamp; - uint16_t MajorVersion; - uint16_t MinorVersion; - uint32_t GlobalFlagsClear; - uint32_t GlobalFlagsSet; - uint32_t CriticalSectionDefaultTimeout; - uint64_t DeCommitFreeBlockThreshold; - uint64_t DeCommitTotalFreeThreshold; - uint64_t LockPrefixTable; // VA - uint64_t MaximumAllocationSize; - uint64_t VirtualMemoryThreshold; - uint64_t ProcessAffinityMask; - uint32_t ProcessHeapFlags; - uint16_t CSDVersion; - uint16_t Reserved1; - uint64_t EditList; // VA - uint64_t SecurityCookie; // VA - uint64_t SEHandlerTable; // VA - uint64_t SEHandlerCount; -}; - -#pragma pack(pop) -} //namespace pe_win - -#ifdef PE_BLISS_WINDOWS -typedef wchar_t unicode16_t; -typedef std::basic_string<unicode16_t> u16string; -#else -//Instead of wchar_t for windows -typedef unsigned short unicode16_t; -typedef std::basic_string<unicode16_t> u16string; -#endif - -} //namespace pe_bliss diff --git a/tools/pe_bliss/pe_tls.cpp b/tools/pe_bliss/pe_tls.cpp deleted file mode 100644 index 5ec68e3f10..0000000000 --- a/tools/pe_bliss/pe_tls.cpp +++ /dev/null @@ -1,396 +0,0 @@ -/*************************************************************************/ -/* Copyright (c) 2015 dx, http://kaimi.ru */ -/* */ -/* Permission is hereby granted, free of charge, to any person */ -/* obtaining a copy of this software and associated documentation */ -/* files (the "Software"), to deal in the Software without */ -/* restriction, including without limitation the rights to use, */ -/* copy, modify, merge, publish, distribute, sublicense, and/or */ -/* sell copies of the Software, and to permit persons to whom the */ -/* Software is furnished to do so, subject to the following conditions: */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#include <string.h> -#include "pe_tls.h" -#include "pe_properties_generic.h" - -namespace pe_bliss -{ -using namespace pe_win; - -//TLS -//Default constructor -tls_info::tls_info() - :start_rva_(0), end_rva_(0), index_rva_(0), callbacks_rva_(0), - size_of_zero_fill_(0), characteristics_(0) -{} - -//Returns start RVA of TLS raw data -uint32_t tls_info::get_raw_data_start_rva() const -{ - return start_rva_; -} - -//Returns end RVA of TLS raw data -uint32_t tls_info::get_raw_data_end_rva() const -{ - return end_rva_; -} - -//Returns TLS index RVA -uint32_t tls_info::get_index_rva() const -{ - return index_rva_; -} - -//Returns TLS callbacks RVA -uint32_t tls_info::get_callbacks_rva() const -{ - return callbacks_rva_; -} - -//Returns size of zero fill -uint32_t tls_info::get_size_of_zero_fill() const -{ - return size_of_zero_fill_; -} - -//Returns characteristics -uint32_t tls_info::get_characteristics() const -{ - return characteristics_; -} - -//Returns raw TLS data -const std::string& tls_info::get_raw_data() const -{ - return raw_data_; -} - -//Returns TLS callbacks addresses -const tls_info::tls_callback_list& tls_info::get_tls_callbacks() const -{ - return callbacks_; -} - -//Returns TLS callbacks addresses -tls_info::tls_callback_list& tls_info::get_tls_callbacks() -{ - return callbacks_; -} - -//Adds TLS callback -void tls_info::add_tls_callback(uint32_t rva) -{ - callbacks_.push_back(rva); -} - -//Clears TLS callbacks list -void tls_info::clear_tls_callbacks() -{ - callbacks_.clear(); -} - -//Recalculates end address of raw TLS data -void tls_info::recalc_raw_data_end_rva() -{ - end_rva_ = static_cast<uint32_t>(start_rva_ + raw_data_.length()); -} - -//Sets start RVA of TLS raw data -void tls_info::set_raw_data_start_rva(uint32_t rva) -{ - start_rva_ = rva; -} - -//Sets end RVA of TLS raw data -void tls_info::set_raw_data_end_rva(uint32_t rva) -{ - end_rva_ = rva; -} - -//Sets TLS index RVA -void tls_info::set_index_rva(uint32_t rva) -{ - index_rva_ = rva; -} - -//Sets TLS callbacks RVA -void tls_info::set_callbacks_rva(uint32_t rva) -{ - callbacks_rva_ = rva; -} - -//Sets size of zero fill -void tls_info::set_size_of_zero_fill(uint32_t size) -{ - size_of_zero_fill_ = size; -} - -//Sets characteristics -void tls_info::set_characteristics(uint32_t characteristics) -{ - characteristics_ = characteristics; -} - -//Sets raw TLS data -void tls_info::set_raw_data(const std::string& data) -{ - raw_data_ = data; -} - -//If image does not have TLS, throws an exception -const tls_info get_tls_info(const pe_base& pe) -{ - return pe.get_pe_type() == pe_type_32 - ? get_tls_info_base<pe_types_class_32>(pe) - : get_tls_info_base<pe_types_class_64>(pe); -} - -//TLS Rebuilder -const image_directory rebuild_tls(pe_base& pe, const tls_info& info, section& tls_section, uint32_t offset_from_section_start, bool write_tls_callbacks, bool write_tls_data, tls_data_expand_type expand, bool save_to_pe_header, bool auto_strip_last_section) -{ - return pe.get_pe_type() == pe_type_32 - ? rebuild_tls_base<pe_types_class_32>(pe, info, tls_section, offset_from_section_start, write_tls_callbacks, write_tls_data, expand, save_to_pe_header, auto_strip_last_section) - : rebuild_tls_base<pe_types_class_64>(pe, info, tls_section, offset_from_section_start, write_tls_callbacks, write_tls_data, expand, save_to_pe_header, auto_strip_last_section); -} - -//Get TLS info -//If image does not have TLS, throws an exception -template<typename PEClassType> -const tls_info get_tls_info_base(const pe_base& pe) -{ - tls_info ret; - - //If there's no TLS directory, throw an exception - if(!pe.has_tls()) - throw pe_exception("Image does not have TLS directory", pe_exception::directory_does_not_exist); - - //Get TLS directory data - typename PEClassType::TLSStruct tls_directory_data = pe.section_data_from_rva<typename PEClassType::TLSStruct>(pe.get_directory_rva(image_directory_entry_tls), section_data_virtual, true); - - //Check data addresses - if(tls_directory_data.EndAddressOfRawData == tls_directory_data.StartAddressOfRawData) - { - try - { - pe.va_to_rva(static_cast<typename PEClassType::BaseSize>(tls_directory_data.EndAddressOfRawData)); - } - catch(const pe_exception&) - { - //Fix addressess on incorrect conversion - tls_directory_data.EndAddressOfRawData = tls_directory_data.StartAddressOfRawData = 0; - } - } - - if(tls_directory_data.StartAddressOfRawData && - pe.section_data_length_from_va(static_cast<typename PEClassType::BaseSize>(tls_directory_data.StartAddressOfRawData), - static_cast<typename PEClassType::BaseSize>(tls_directory_data.StartAddressOfRawData), section_data_virtual, true) - < (tls_directory_data.EndAddressOfRawData - tls_directory_data.StartAddressOfRawData)) - throw pe_exception("Incorrect TLS directory", pe_exception::incorrect_tls_directory); - - //Fill TLS info - //VAs are not checked - ret.set_raw_data_start_rva(tls_directory_data.StartAddressOfRawData ? pe.va_to_rva(static_cast<typename PEClassType::BaseSize>(tls_directory_data.StartAddressOfRawData)) : 0); - ret.set_raw_data_end_rva(tls_directory_data.EndAddressOfRawData ? pe.va_to_rva(static_cast<typename PEClassType::BaseSize>(tls_directory_data.EndAddressOfRawData)) : 0); - ret.set_index_rva(tls_directory_data.AddressOfIndex ? pe.va_to_rva(static_cast<typename PEClassType::BaseSize>(tls_directory_data.AddressOfIndex)) : 0); - ret.set_callbacks_rva(tls_directory_data.AddressOfCallBacks ? pe.va_to_rva(static_cast<typename PEClassType::BaseSize>(tls_directory_data.AddressOfCallBacks)) : 0); - ret.set_size_of_zero_fill(tls_directory_data.SizeOfZeroFill); - ret.set_characteristics(tls_directory_data.Characteristics); - - if(tls_directory_data.StartAddressOfRawData && tls_directory_data.StartAddressOfRawData != tls_directory_data.EndAddressOfRawData) - { - //Read and save TLS RAW data - ret.set_raw_data(std::string( - pe.section_data_from_va(static_cast<typename PEClassType::BaseSize>(tls_directory_data.StartAddressOfRawData), section_data_virtual, true), - static_cast<uint32_t>(tls_directory_data.EndAddressOfRawData - tls_directory_data.StartAddressOfRawData))); - } - - //If file has TLS callbacks - if(ret.get_callbacks_rva()) - { - //Read callbacks VAs - uint32_t current_tls_callback = 0; - - while(true) - { - //Read TLS callback VA - typename PEClassType::BaseSize va = pe.section_data_from_va<typename PEClassType::BaseSize>(static_cast<typename PEClassType::BaseSize>(tls_directory_data.AddressOfCallBacks + current_tls_callback), section_data_virtual, true); - if(va == 0) - break; - - //Save it - ret.add_tls_callback(pe.va_to_rva(va, false)); - - //Move to next callback VA - current_tls_callback += sizeof(va); - } - } - - return ret; -} - -//Rebuilder of TLS structures -//If write_tls_callbacks = true, TLS callbacks VAs will be written to their place -//If write_tls_data = true, TLS data will be written to its place -//If you have chosen to rewrite raw data, only (EndAddressOfRawData - StartAddressOfRawData) bytes will be written, not the full length of string -//representing raw data content -//auto_strip_last_section - if true and TLS are placed in the last section, it will be automatically stripped -//Note/TODO: TLS Callbacks array is not DWORD-aligned (seems to work on WinXP - Win7) -template<typename PEClassType> -const image_directory rebuild_tls_base(pe_base& pe, const tls_info& info, section& tls_section, uint32_t offset_from_section_start, bool write_tls_callbacks, bool write_tls_data, tls_data_expand_type expand, bool save_to_pe_header, bool auto_strip_last_section) -{ - //Check that tls_section is attached to this PE image - if(!pe.section_attached(tls_section)) - throw pe_exception("TLS section must be attached to PE file", pe_exception::section_is_not_attached); - - uint32_t tls_data_pos = pe_utils::align_up(offset_from_section_start, sizeof(typename PEClassType::BaseSize)); - uint32_t needed_size = sizeof(typename PEClassType::TLSStruct); //Calculate needed size for TLS table - - //Check if tls_section is last one. If it's not, check if there's enough place for TLS data - if(&tls_section != &*(pe.get_image_sections().end() - 1) && - (tls_section.empty() || pe_utils::align_up(tls_section.get_size_of_raw_data(), pe.get_file_alignment()) < needed_size + tls_data_pos)) - throw pe_exception("Insufficient space for TLS directory", pe_exception::insufficient_space); - - //Check raw data positions - if(info.get_raw_data_end_rva() < info.get_raw_data_start_rva() || info.get_index_rva() == 0) - throw pe_exception("Incorrect TLS directory", pe_exception::incorrect_tls_directory); - - std::string& raw_data = tls_section.get_raw_data(); - - //This will be done only if tls_section is the last section of image or for section with unaligned raw length of data - if(raw_data.length() < needed_size + tls_data_pos) - raw_data.resize(needed_size + tls_data_pos); //Expand section raw data - - //Create and fill TLS structure - typename PEClassType::TLSStruct tls_struct = {0}; - - typename PEClassType::BaseSize va; - if(info.get_raw_data_start_rva()) - { - pe.rva_to_va(info.get_raw_data_start_rva(), va); - tls_struct.StartAddressOfRawData = va; - tls_struct.SizeOfZeroFill = info.get_size_of_zero_fill(); - } - - if(info.get_raw_data_end_rva()) - { - pe.rva_to_va(info.get_raw_data_end_rva(), va); - tls_struct.EndAddressOfRawData = va; - } - - pe.rva_to_va(info.get_index_rva(), va); - tls_struct.AddressOfIndex = va; - - if(info.get_callbacks_rva()) - { - pe.rva_to_va(info.get_callbacks_rva(), va); - tls_struct.AddressOfCallBacks = va; - } - - tls_struct.Characteristics = info.get_characteristics(); - - //Save TLS structure - memcpy(&raw_data[tls_data_pos], &tls_struct, sizeof(tls_struct)); - - //If we are asked to rewrite TLS raw data - if(write_tls_data && info.get_raw_data_start_rva() && info.get_raw_data_start_rva() != info.get_raw_data_end_rva()) - { - try - { - //Check if we're going to write TLS raw data to an existing section (not to PE headers) - section& raw_data_section = pe.section_from_rva(info.get_raw_data_start_rva()); - pe.expand_section(raw_data_section, info.get_raw_data_start_rva(), info.get_raw_data_end_rva() - info.get_raw_data_start_rva(), expand == tls_data_expand_raw ? pe_base::expand_section_raw : pe_base::expand_section_virtual); - } - catch(const pe_exception&) - { - //If no section is presented by StartAddressOfRawData, just go to next step - } - - unsigned long write_raw_data_size = info.get_raw_data_end_rva() - info.get_raw_data_start_rva(); - unsigned long available_raw_length = 0; - - //Check if there's enough RAW space to write raw TLS data... - if((available_raw_length = pe.section_data_length_from_rva(info.get_raw_data_start_rva(), info.get_raw_data_start_rva(), section_data_raw, true)) - < info.get_raw_data_end_rva() - info.get_raw_data_start_rva()) - { - //Check if there's enough virtual space for it... - if(pe.section_data_length_from_rva(info.get_raw_data_start_rva(), info.get_raw_data_start_rva(), section_data_virtual, true) - < info.get_raw_data_end_rva() - info.get_raw_data_start_rva()) - throw pe_exception("Insufficient space for TLS raw data", pe_exception::insufficient_space); - else - write_raw_data_size = available_raw_length; //We'll write just a part of full raw data - } - - //Write raw TLS data, if any - if(write_raw_data_size != 0) - memcpy(pe.section_data_from_rva(info.get_raw_data_start_rva(), true), info.get_raw_data().data(), write_raw_data_size); - } - - //If we are asked to rewrite TLS callbacks addresses - if(write_tls_callbacks && info.get_callbacks_rva()) - { - unsigned long needed_callback_size = static_cast<unsigned long>((info.get_tls_callbacks().size() + 1 /* last null element */) * sizeof(typename PEClassType::BaseSize)); - - try - { - //Check if we're going to write TLS callbacks VAs to an existing section (not to PE headers) - section& raw_data_section = pe.section_from_rva(info.get_callbacks_rva()); - pe.expand_section(raw_data_section, info.get_callbacks_rva(), needed_callback_size, pe_base::expand_section_raw); - } - catch(const pe_exception&) - { - //If no section is presented by RVA of callbacks, just go to next step - } - - //Check if there's enough space to write callbacks TLS data... - if(pe.section_data_length_from_rva(info.get_callbacks_rva(), info.get_callbacks_rva(), section_data_raw, true) - < needed_callback_size - sizeof(typename PEClassType::BaseSize) /* last zero element can be virtual only */) - throw pe_exception("Insufficient space for TLS callbacks data", pe_exception::insufficient_space); - - if(pe.section_data_length_from_rva(info.get_callbacks_rva(), info.get_callbacks_rva(), section_data_virtual, true) - < needed_callback_size /* check here full virtual data length available */) - throw pe_exception("Insufficient space for TLS callbacks data", pe_exception::insufficient_space); - - std::vector<typename PEClassType::BaseSize> callbacks_virtual_addresses; - callbacks_virtual_addresses.reserve(info.get_tls_callbacks().size() + 1 /* last null element */); - - //Convert TLS RVAs to VAs - for(tls_info::tls_callback_list::const_iterator it = info.get_tls_callbacks().begin(); it != info.get_tls_callbacks().end(); ++it) - { - typename PEClassType::BaseSize cb_va = 0; - pe.rva_to_va(*it, cb_va); - callbacks_virtual_addresses.push_back(cb_va); - } - - //Ending null element - callbacks_virtual_addresses.push_back(0); - - //Write callbacks TLS data - memcpy(pe.section_data_from_rva(info.get_callbacks_rva(), true), &callbacks_virtual_addresses[0], needed_callback_size); - } - - //Adjust section raw and virtual sizes - pe.recalculate_section_sizes(tls_section, auto_strip_last_section); - - image_directory ret(pe.rva_from_section_offset(tls_section, tls_data_pos), needed_size); - - //If auto-rewrite of PE headers is required - if(save_to_pe_header) - { - pe.set_directory_rva(image_directory_entry_tls, ret.get_rva()); - pe.set_directory_size(image_directory_entry_tls, ret.get_size()); - } - - return ret; -} -} diff --git a/tools/pe_bliss/pe_tls.h b/tools/pe_bliss/pe_tls.h deleted file mode 100644 index 316e208147..0000000000 --- a/tools/pe_bliss/pe_tls.h +++ /dev/null @@ -1,122 +0,0 @@ -/*************************************************************************/ -/* Copyright (c) 2015 dx, http://kaimi.ru */ -/* */ -/* Permission is hereby granted, free of charge, to any person */ -/* obtaining a copy of this software and associated documentation */ -/* files (the "Software"), to deal in the Software without */ -/* restriction, including without limitation the rights to use, */ -/* copy, modify, merge, publish, distribute, sublicense, and/or */ -/* sell copies of the Software, and to permit persons to whom the */ -/* Software is furnished to do so, subject to the following conditions: */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#pragma once -#include <memory> -#include <istream> -#include "pe_base.h" -#include "pe_directory.h" - -namespace pe_bliss -{ -//Class representing TLS info -//We use "DWORD" type to represent RVAs, because RVA is -//always 32bit even in PE+ -class tls_info -{ -public: - typedef std::vector<uint32_t> tls_callback_list; - -public: - //Default constructor - tls_info(); - - //Returns start RVA of TLS raw data - uint32_t get_raw_data_start_rva() const; - //Returns end RVA of TLS raw data - uint32_t get_raw_data_end_rva() const; - //Returns TLS index RVA - uint32_t get_index_rva() const; - //Returns TLS callbacks RVA - uint32_t get_callbacks_rva() const; - //Returns size of zero fill - uint32_t get_size_of_zero_fill() const; - //Returns characteristics - uint32_t get_characteristics() const; - //Returns raw TLS data - const std::string& get_raw_data() const; - //Returns TLS callbacks addresses - const tls_callback_list& get_tls_callbacks() const; - -public: //These functions do not change everything inside image, they are used by PE class - //You can also use them to rebuild TLS directory - - //Sets start RVA of TLS raw data - void set_raw_data_start_rva(uint32_t rva); - //Sets end RVA of TLS raw data - void set_raw_data_end_rva(uint32_t rva); - //Sets TLS index RVA - void set_index_rva(uint32_t rva); - //Sets TLS callbacks RVA - void set_callbacks_rva(uint32_t rva); - //Sets size of zero fill - void set_size_of_zero_fill(uint32_t size); - //Sets characteristics - void set_characteristics(uint32_t characteristics); - //Sets raw TLS data - void set_raw_data(const std::string& data); - //Returns TLS callbacks addresses - tls_callback_list& get_tls_callbacks(); - //Adds TLS callback - void add_tls_callback(uint32_t rva); - //Clears TLS callbacks list - void clear_tls_callbacks(); - //Recalculates end address of raw TLS data - void recalc_raw_data_end_rva(); - -private: - uint32_t start_rva_, end_rva_, index_rva_, callbacks_rva_; - uint32_t size_of_zero_fill_, characteristics_; - - //Raw TLS data - std::string raw_data_; - - //TLS callback RVAs - tls_callback_list callbacks_; -}; - -//Represents type of expanding of TLS section containing raw data -//(Works only if you are writing TLS raw data to tls_section and it is the last one in the PE image on the moment of TLS rebuild) -enum tls_data_expand_type -{ - tls_data_expand_raw, //If there is not enough raw space for raw TLS data, it can be expanded - tls_data_expand_virtual //If there is not enough virtual place for raw TLS data, it can be expanded -}; - - -//Get TLS info -//If image does not have TLS, throws an exception -const tls_info get_tls_info(const pe_base& pe); - -template<typename PEClassType> -const tls_info get_tls_info_base(const pe_base& pe); - -//Rebuilder of TLS structures -//If write_tls_callbacks = true, TLS callbacks VAs will be written to their place -//If write_tls_data = true, TLS data will be written to its place -//If you have chosen to rewrite raw data, only (EndAddressOfRawData - StartAddressOfRawData) bytes will be written, not the full length of string -//representing raw data content -//auto_strip_last_section - if true and TLS are placed in the last section, it will be automatically stripped -const image_directory rebuild_tls(pe_base& pe, const tls_info& info, section& tls_section, uint32_t offset_from_section_start = 0, bool write_tls_callbacks = true, bool write_tls_data = true, tls_data_expand_type expand = tls_data_expand_raw, bool save_to_pe_header = true, bool auto_strip_last_section = true); - -template<typename PEClassType> -const image_directory rebuild_tls_base(pe_base& pe, const tls_info& info, section& tls_section, uint32_t offset_from_section_start = 0, bool write_tls_callbacks = true, bool write_tls_data = true, tls_data_expand_type expand = tls_data_expand_raw, bool save_to_pe_header = true, bool auto_strip_last_section = true); -} diff --git a/tools/pe_bliss/resource_bitmap_reader.cpp b/tools/pe_bliss/resource_bitmap_reader.cpp deleted file mode 100644 index 3546461f53..0000000000 --- a/tools/pe_bliss/resource_bitmap_reader.cpp +++ /dev/null @@ -1,86 +0,0 @@ -/*************************************************************************/ -/* Copyright (c) 2015 dx, http://kaimi.ru */ -/* */ -/* Permission is hereby granted, free of charge, to any person */ -/* obtaining a copy of this software and associated documentation */ -/* files (the "Software"), to deal in the Software without */ -/* restriction, including without limitation the rights to use, */ -/* copy, modify, merge, publish, distribute, sublicense, and/or */ -/* sell copies of the Software, and to permit persons to whom the */ -/* Software is furnished to do so, subject to the following conditions: */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#include <cmath> -#include "resource_bitmap_reader.h" -#include "pe_resource_viewer.h" -#include "pe_structures.h" - -namespace pe_bliss -{ -using namespace pe_win; - -resource_bitmap_reader::resource_bitmap_reader(const pe_resource_viewer& res) - :res_(res) -{} - -//Returns bitmap data by name and index in language directory (instead of language) (minimum checks of format correctness) -const std::string resource_bitmap_reader::get_bitmap_by_name(const std::wstring& name, uint32_t index) const -{ - return create_bitmap(res_.get_resource_data_by_name(pe_resource_viewer::resource_bitmap, name, index).get_data()); -} - -//Returns bitmap data by name and language (minimum checks of format correctness) -const std::string resource_bitmap_reader::get_bitmap_by_name(uint32_t language, const std::wstring& name) const -{ - return create_bitmap(res_.get_resource_data_by_name(language, pe_resource_viewer::resource_bitmap, name).get_data()); -} - -//Returns bitmap data by ID and language (minimum checks of format correctness) -const std::string resource_bitmap_reader::get_bitmap_by_id_lang(uint32_t language, uint32_t id) const -{ - return create_bitmap(res_.get_resource_data_by_id(language, pe_resource_viewer::resource_bitmap, id).get_data()); -} - -//Returns bitmap data by ID and index in language directory (instead of language) (minimum checks of format correctness) -const std::string resource_bitmap_reader::get_bitmap_by_id(uint32_t id, uint32_t index) const -{ - return create_bitmap(res_.get_resource_data_by_id(pe_resource_viewer::resource_bitmap, id, index).get_data()); -} - -//Helper function of creating bitmap header -const std::string resource_bitmap_reader::create_bitmap(const std::string& resource_data) -{ - //Create bitmap file header - bitmapfileheader header = {0}; - header.bfType = 0x4d42; //Signature "BM" - header.bfOffBits = sizeof(bitmapfileheader) + sizeof(bitmapinfoheader); //Offset to bitmap bits - header.bfSize = static_cast<uint32_t>(sizeof(bitmapfileheader) + resource_data.length()); //Size of bitmap - - //Check size of resource data - if(resource_data.length() < sizeof(bitmapinfoheader)) - throw pe_exception("Incorrect resource bitmap", pe_exception::resource_incorrect_bitmap); - - { - //Get bitmap info header - const bitmapinfoheader* info = reinterpret_cast<const bitmapinfoheader*>(resource_data.data()); - - //If color table is present, skip it - if(info->biClrUsed != 0) - header.bfOffBits += 4 * info->biClrUsed; //Add this size to offset to bitmap bits - else if(info->biBitCount <= 8) - header.bfOffBits += 4 * static_cast<uint32_t>(std::pow(2.f, info->biBitCount)); //Add this size to offset to bitmap bits - } - - //Return final bitmap data - return std::string(reinterpret_cast<const char*>(&header), sizeof(bitmapfileheader)) + resource_data; -} -} diff --git a/tools/pe_bliss/resource_bitmap_reader.h b/tools/pe_bliss/resource_bitmap_reader.h deleted file mode 100644 index f2b92bbde7..0000000000 --- a/tools/pe_bliss/resource_bitmap_reader.h +++ /dev/null @@ -1,50 +0,0 @@ -/*************************************************************************/ -/* Copyright (c) 2015 dx, http://kaimi.ru */ -/* */ -/* Permission is hereby granted, free of charge, to any person */ -/* obtaining a copy of this software and associated documentation */ -/* files (the "Software"), to deal in the Software without */ -/* restriction, including without limitation the rights to use, */ -/* copy, modify, merge, publish, distribute, sublicense, and/or */ -/* sell copies of the Software, and to permit persons to whom the */ -/* Software is furnished to do so, subject to the following conditions: */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#pragma once -#include <string> -#include "stdint_defs.h" - -namespace pe_bliss -{ -class pe_resource_viewer; - -class resource_bitmap_reader -{ -public: - resource_bitmap_reader(const pe_resource_viewer& res); - - //Returns bitmap data by name and language (minimum checks of format correctness) - const std::string get_bitmap_by_name(uint32_t language, const std::wstring& name) const; - //Returns bitmap data by name and index in language directory (instead of language) (minimum checks of format correctness) - const std::string get_bitmap_by_name(const std::wstring& name, uint32_t index = 0) const; - //Returns bitmap data by ID and language (minimum checks of format correctness) - const std::string get_bitmap_by_id_lang(uint32_t language, uint32_t id) const; - //Returns bitmap data by ID and index in language directory (instead of language) (minimum checks of format correctness) - const std::string get_bitmap_by_id(uint32_t id, uint32_t index = 0) const; - -private: - //Helper function of creating bitmap header - static const std::string create_bitmap(const std::string& resource_data); - - const pe_resource_viewer& res_; -}; -} diff --git a/tools/pe_bliss/resource_bitmap_writer.cpp b/tools/pe_bliss/resource_bitmap_writer.cpp deleted file mode 100644 index 3445a08445..0000000000 --- a/tools/pe_bliss/resource_bitmap_writer.cpp +++ /dev/null @@ -1,75 +0,0 @@ -/*************************************************************************/ -/* Copyright (c) 2015 dx, http://kaimi.ru */ -/* */ -/* Permission is hereby granted, free of charge, to any person */ -/* obtaining a copy of this software and associated documentation */ -/* files (the "Software"), to deal in the Software without */ -/* restriction, including without limitation the rights to use, */ -/* copy, modify, merge, publish, distribute, sublicense, and/or */ -/* sell copies of the Software, and to permit persons to whom the */ -/* Software is furnished to do so, subject to the following conditions: */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#include "resource_bitmap_writer.h" -#include "pe_resource_manager.h" -#include "pe_structures.h" - -namespace pe_bliss -{ -using namespace pe_win; - -resource_bitmap_writer::resource_bitmap_writer(pe_resource_manager& res) - :res_(res) -{} - -//Adds bitmap from bitmap file data. If bitmap already exists, replaces it -//timestamp will be used for directories that will be added -void resource_bitmap_writer::add_bitmap(const std::string& bitmap_file, uint32_t id, uint32_t language, uint32_t codepage, uint32_t timestamp) -{ - //Check bitmap data a little - if(bitmap_file.length() < sizeof(bitmapfileheader)) - throw pe_exception("Incorrect resource bitmap", pe_exception::resource_incorrect_bitmap); - - resource_directory_entry new_entry; - new_entry.set_id(id); - - //Add bitmap - res_.add_resource(bitmap_file.substr(sizeof(bitmapfileheader)), pe_resource_viewer::resource_bitmap, new_entry, resource_directory::entry_finder(id), language, codepage, timestamp); -} - -//Adds bitmap from bitmap file data. If bitmap already exists, replaces it -//timestamp will be used for directories that will be added -void resource_bitmap_writer::add_bitmap(const std::string& bitmap_file, const std::wstring& name, uint32_t language, uint32_t codepage, uint32_t timestamp) -{ - //Check bitmap data a little - if(bitmap_file.length() < sizeof(bitmapfileheader)) - throw pe_exception("Incorrect resource bitmap", pe_exception::resource_incorrect_bitmap); - - resource_directory_entry new_entry; - new_entry.set_name(name); - - //Add bitmap - res_.add_resource(bitmap_file.substr(sizeof(bitmapfileheader)), pe_resource_viewer::resource_bitmap, new_entry, resource_directory::entry_finder(name), language, codepage, timestamp); -} - -//Removes bitmap by name/ID and language -bool resource_bitmap_writer::remove_bitmap(const std::wstring& name, uint32_t language) -{ - return res_.remove_resource(pe_resource_viewer::resource_bitmap, name, language); -} - -//Removes bitmap by name/ID and language -bool resource_bitmap_writer::remove_bitmap(uint32_t id, uint32_t language) -{ - return res_.remove_resource(pe_resource_viewer::resource_bitmap, id, language); -} -} diff --git a/tools/pe_bliss/resource_bitmap_writer.h b/tools/pe_bliss/resource_bitmap_writer.h deleted file mode 100644 index 4b8ea72705..0000000000 --- a/tools/pe_bliss/resource_bitmap_writer.h +++ /dev/null @@ -1,47 +0,0 @@ -/*************************************************************************/ -/* Copyright (c) 2015 dx, http://kaimi.ru */ -/* */ -/* Permission is hereby granted, free of charge, to any person */ -/* obtaining a copy of this software and associated documentation */ -/* files (the "Software"), to deal in the Software without */ -/* restriction, including without limitation the rights to use, */ -/* copy, modify, merge, publish, distribute, sublicense, and/or */ -/* sell copies of the Software, and to permit persons to whom the */ -/* Software is furnished to do so, subject to the following conditions: */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#pragma once -#include <string> -#include "stdint_defs.h" - -namespace pe_bliss -{ -class pe_resource_manager; - -class resource_bitmap_writer -{ -public: - resource_bitmap_writer(pe_resource_manager& res); - - //Adds bitmap from bitmap file data. If bitmap already exists, replaces it - //timestamp will be used for directories that will be added - void add_bitmap(const std::string& bitmap_file, uint32_t id, uint32_t language, uint32_t codepage = 0, uint32_t timestamp = 0); - void add_bitmap(const std::string& bitmap_file, const std::wstring& name, uint32_t language, uint32_t codepage = 0, uint32_t timestamp = 0); - - //Removes bitmap by name/ID and language - bool remove_bitmap(const std::wstring& name, uint32_t language); - bool remove_bitmap(uint32_t id, uint32_t language); - -private: - pe_resource_manager& res_; -}; -} diff --git a/tools/pe_bliss/resource_cursor_icon_reader.cpp b/tools/pe_bliss/resource_cursor_icon_reader.cpp deleted file mode 100644 index 28a259163e..0000000000 --- a/tools/pe_bliss/resource_cursor_icon_reader.cpp +++ /dev/null @@ -1,521 +0,0 @@ -/*************************************************************************/ -/* Copyright (c) 2015 dx, http://kaimi.ru */ -/* */ -/* Permission is hereby granted, free of charge, to any person */ -/* obtaining a copy of this software and associated documentation */ -/* files (the "Software"), to deal in the Software without */ -/* restriction, including without limitation the rights to use, */ -/* copy, modify, merge, publish, distribute, sublicense, and/or */ -/* sell copies of the Software, and to permit persons to whom the */ -/* Software is furnished to do so, subject to the following conditions: */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#include <algorithm> -#include "resource_cursor_icon_reader.h" -#include "pe_structures.h" -#include "pe_resource_viewer.h" - -namespace pe_bliss -{ -using namespace pe_win; - -resource_cursor_icon_reader::resource_cursor_icon_reader(const pe_resource_viewer& res) - :res_(res) -{} - -//Helper function of creating icon headers from ICON_GROUP resource data -//Returns icon count -uint16_t resource_cursor_icon_reader::format_icon_headers(std::string& ico_data, const std::string& resource_data) -{ - //Check resource data size - if(resource_data.length() < sizeof(ico_header)) - throw pe_exception("Incorrect resource icon", pe_exception::resource_incorrect_icon); - - //Get icon header - const ico_header* info = reinterpret_cast<const ico_header*>(resource_data.data()); - - //Check resource data size - if(resource_data.length() < sizeof(ico_header) + info->Count * sizeof(icon_group)) - throw pe_exception("Incorrect resource icon", pe_exception::resource_incorrect_icon); - - //Reserve memory to speed up a little - ico_data.reserve(sizeof(ico_header) + info->Count * sizeof(icondirentry)); - ico_data.append(reinterpret_cast<const char*>(info), sizeof(ico_header)); - - //Iterate over all listed icons - uint32_t offset = sizeof(ico_header) + sizeof(icondirentry) * info->Count; - for(uint16_t i = 0; i != info->Count; ++i) - { - const icon_group* group = reinterpret_cast<const icon_group*>(resource_data.data() + sizeof(ico_header) + i * sizeof(icon_group)); - - //Fill icon data - icondirentry direntry; - direntry.BitCount = group->BitCount; - direntry.ColorCount = group->ColorCount; - direntry.Height = group->Height; - direntry.Planes = group->Planes; - direntry.Reserved = group->Reserved; - direntry.SizeInBytes = group->SizeInBytes; - direntry.Width = group->Width; - direntry.ImageOffset = offset; - - //Add icon header to returned value - ico_data.append(reinterpret_cast<const char*>(&direntry), sizeof(icondirentry)); - - offset += group->SizeInBytes; - } - - //Return icon count - return info->Count; -} - -//Returns single icon data by ID and language (minimum checks of format correctness) -const std::string resource_cursor_icon_reader::get_single_icon_by_id_lang(uint32_t language, uint32_t id) const -{ - //Get icon headers - std::string icon_data(lookup_icon_group_data_by_icon(id, language)); - //Append icon data - icon_data.append(res_.get_resource_data_by_id(language, pe_resource_viewer::resource_icon, id).get_data()); - return icon_data; -} - -//Returns single icon data by ID and index in language directory (instead of language) (minimum checks of format correctness) -const std::string resource_cursor_icon_reader::get_single_icon_by_id(uint32_t id, uint32_t index) const -{ - pe_resource_viewer::resource_language_list languages(res_.list_resource_languages(pe_resource_viewer::resource_icon, id)); - if(languages.size() <= index) - throw pe_exception("Resource data entry not found", pe_exception::resource_data_entry_not_found); - - //Get icon headers - std::string icon_data(lookup_icon_group_data_by_icon(id, languages.at(index))); - //Append icon data - icon_data.append(res_.get_resource_data_by_id(pe_resource_viewer::resource_icon, id, index).get_data()); - return icon_data; -} - -//Returns icon data by name and index in language directory (instead of language) (minimum checks of format correctness) -const std::string resource_cursor_icon_reader::get_icon_by_name(const std::wstring& name, uint32_t index) const -{ - std::string ret; - - //Get resource by name and index - const std::string data = res_.get_resource_data_by_name(pe_resource_viewer::resource_icon_group, name, index).get_data(); - - //Create icon headers - uint16_t icon_count = format_icon_headers(ret, data); - - //Append icon data - for(uint16_t i = 0; i != icon_count; ++i) - { - const icon_group* group = reinterpret_cast<const icon_group*>(data.data() + sizeof(ico_header) + i * sizeof(icon_group)); - ret += res_.get_resource_data_by_id(pe_resource_viewer::resource_icon, group->Number, index).get_data(); - } - - return ret; -} - -//Returns icon data by name and language (minimum checks of format correctness) -const std::string resource_cursor_icon_reader::get_icon_by_name(uint32_t language, const std::wstring& name) const -{ - std::string ret; - - //Get resource by name and language - const std::string data = res_.get_resource_data_by_name(language, pe_resource_viewer::resource_icon_group, name).get_data(); - - //Create icon headers - uint16_t icon_count = format_icon_headers(ret, data); - - //Append icon data - for(uint16_t i = 0; i != icon_count; ++i) - { - const icon_group* group = reinterpret_cast<const icon_group*>(data.data() + sizeof(ico_header) + i * sizeof(icon_group)); - ret += res_.get_resource_data_by_id(language, pe_resource_viewer::resource_icon, group->Number).get_data(); - } - - return ret; -} - -//Returns icon data by ID and language (minimum checks of format correctness) -const std::string resource_cursor_icon_reader::get_icon_by_id_lang(uint32_t language, uint32_t id) const -{ - std::string ret; - - //Get resource by language and id - const std::string data = res_.get_resource_data_by_id(language, pe_resource_viewer::resource_icon_group, id).get_data(); - - //Create icon headers - uint16_t icon_count = format_icon_headers(ret, data); - - //Append icon data - for(uint16_t i = 0; i != icon_count; ++i) - { - const icon_group* group = reinterpret_cast<const icon_group*>(data.data() + sizeof(ico_header) + i * sizeof(icon_group)); - ret += res_.get_resource_data_by_id(language, pe_resource_viewer::resource_icon, group->Number).get_data(); - } - - return ret; -} - -//Returns icon data by ID and index in language directory (instead of language) (minimum checks of format correctness) -const std::string resource_cursor_icon_reader::get_icon_by_id(uint32_t id, uint32_t index) const -{ - std::string ret; - - //Get resource by id and index - const std::string data = res_.get_resource_data_by_id(pe_resource_viewer::resource_icon_group, id, index).get_data(); - - //Create icon headers - uint16_t icon_count = format_icon_headers(ret, data); - - //Append icon data - for(uint16_t i = 0; i != icon_count; ++i) - { - const icon_group* group = reinterpret_cast<const icon_group*>(data.data() + sizeof(ico_header) + i * sizeof(icon_group)); - ret += res_.get_resource_data_by_id(pe_resource_viewer::resource_icon, group->Number, index).get_data(); - } - - return ret; -} - -//Checks for icon presence inside icon group, fills icon headers if found -bool resource_cursor_icon_reader::check_icon_presence(const std::string& icon_group_resource_data, uint32_t icon_id, std::string& ico_data) -{ - //Check resource data size - if(icon_group_resource_data.length() < sizeof(ico_header)) - throw pe_exception("Incorrect resource icon", pe_exception::resource_incorrect_icon); - - //Get icon header - const ico_header* info = reinterpret_cast<const ico_header*>(icon_group_resource_data.data()); - - //Check resource data size - if(icon_group_resource_data.length() < sizeof(ico_header) + info->Count * sizeof(icon_group)) - throw pe_exception("Incorrect resource icon", pe_exception::resource_incorrect_icon); - - for(uint16_t i = 0; i != info->Count; ++i) - { - const icon_group* group = reinterpret_cast<const icon_group*>(icon_group_resource_data.data() + sizeof(ico_header) + i * sizeof(icon_group)); - if(group->Number == icon_id) - { - //Reserve memory to speed up a little - ico_data.reserve(sizeof(ico_header) + sizeof(icondirentry)); - //Write single-icon icon header - ico_header new_header = *info; - new_header.Count = 1; - ico_data.append(reinterpret_cast<const char*>(&new_header), sizeof(ico_header)); - - //Fill icon data - icondirentry direntry; - direntry.BitCount = group->BitCount; - direntry.ColorCount = group->ColorCount; - direntry.Height = group->Height; - direntry.Planes = group->Planes; - direntry.Reserved = group->Reserved; - direntry.SizeInBytes = group->SizeInBytes; - direntry.Width = group->Width; - direntry.ImageOffset = sizeof(ico_header) + sizeof(icondirentry); - ico_data.append(reinterpret_cast<const char*>(&direntry), sizeof(direntry)); - - return true; - } - } - - return false; -} - -//Looks up icon group by icon id and returns full icon headers if found -const std::string resource_cursor_icon_reader::lookup_icon_group_data_by_icon(uint32_t icon_id, uint32_t language) const -{ - std::string icon_header_data; - - { - //List all ID-resources - pe_resource_viewer::resource_id_list ids(res_.list_resource_ids(pe_resource_viewer::resource_icon_group)); - - for(pe_resource_viewer::resource_id_list::const_iterator it = ids.begin(); it != ids.end(); ++it) - { - pe_resource_viewer::resource_language_list group_languages(res_.list_resource_languages(pe_resource_viewer::resource_icon_group, *it)); - if(std::find(group_languages.begin(), group_languages.end(), language) != group_languages.end() - && check_icon_presence(res_.get_resource_data_by_id(language, pe_resource_viewer::resource_icon_group, *it).get_data(), icon_id, icon_header_data)) - return icon_header_data; - } - } - - { - //List all named resources - pe_resource_viewer::resource_name_list names(res_.list_resource_names(pe_resource_viewer::resource_icon_group)); - for(pe_resource_viewer::resource_name_list::const_iterator it = names.begin(); it != names.end(); ++it) - { - pe_resource_viewer::resource_language_list group_languages(res_.list_resource_languages(pe_resource_viewer::resource_icon_group, *it)); - if(std::find(group_languages.begin(), group_languages.end(), language) != group_languages.end() - && check_icon_presence(res_.get_resource_data_by_name(language, pe_resource_viewer::resource_icon_group, *it).get_data(), icon_id, icon_header_data)) - return icon_header_data; - } - } - - throw pe_exception("No icon group find for requested icon", pe_exception::no_icon_group_found); -} - -//Returns single cursor data by ID and language (minimum checks of format correctness) -const std::string resource_cursor_icon_reader::get_single_cursor_by_id_lang(uint32_t language, uint32_t id) const -{ - std::string raw_cursor_data(res_.get_resource_data_by_id(language, pe_resource_viewer::resource_cursor, id).get_data()); - //Get cursor headers - std::string cursor_data(lookup_cursor_group_data_by_cursor(id, language, raw_cursor_data)); - //Append cursor data - cursor_data.append(raw_cursor_data.substr(sizeof(uint16_t) * 2 /* hotspot position */)); - return cursor_data; -} - -//Returns single cursor data by ID and index in language directory (instead of language) (minimum checks of format correctness) -const std::string resource_cursor_icon_reader::get_single_cursor_by_id(uint32_t id, uint32_t index) const -{ - pe_resource_viewer::resource_language_list languages(res_.list_resource_languages(pe_resource_viewer::resource_cursor, id)); - if(languages.size() <= index) - throw pe_exception("Resource data entry not found", pe_exception::resource_data_entry_not_found); - - std::string raw_cursor_data(res_.get_resource_data_by_id(pe_resource_viewer::resource_cursor, id, index).get_data()); - //Get cursor headers - std::string cursor_data(lookup_cursor_group_data_by_cursor(id, languages.at(index), raw_cursor_data)); - //Append cursor data - cursor_data.append(raw_cursor_data.substr(sizeof(uint16_t) * 2 /* hotspot position */)); - return cursor_data; -} - -//Helper function of creating cursor headers -//Returns cursor count -uint16_t resource_cursor_icon_reader::format_cursor_headers(std::string& cur_data, const std::string& resource_data, uint32_t language, uint32_t index) const -{ - //Check resource data length - if(resource_data.length() < sizeof(cursor_header)) - throw pe_exception("Incorrect resource cursor", pe_exception::resource_incorrect_cursor); - - const cursor_header* info = reinterpret_cast<const cursor_header*>(resource_data.data()); - - //Check resource data length - if(resource_data.length() < sizeof(cursor_header) + sizeof(cursor_group) * info->Count) - throw pe_exception("Incorrect resource cursor", pe_exception::resource_incorrect_cursor); - - //Reserve needed space to speed up a little - cur_data.reserve(sizeof(cursor_header) + info->Count * sizeof(cursordirentry)); - //Add cursor header - cur_data.append(reinterpret_cast<const char*>(info), sizeof(cursor_header)); - - //Iterate over all cursors listed in cursor group - uint32_t offset = sizeof(cursor_header) + sizeof(cursordirentry) * info->Count; - for(uint16_t i = 0; i != info->Count; ++i) - { - const cursor_group* group = reinterpret_cast<const cursor_group*>(resource_data.data() + sizeof(cursor_header) + i * sizeof(cursor_group)); - - //Fill cursor info - cursordirentry direntry; - direntry.ColorCount = 0; //OK - direntry.Width = static_cast<uint8_t>(group->Width); - direntry.Height = static_cast<uint8_t>(group->Height) / 2; - direntry.Reserved = 0; - - //Now read hotspot data from cursor data directory - const std::string cursor = index == 0xFFFFFFFF - ? res_.get_resource_data_by_id(language, pe_resource_viewer::resource_cursor, group->Number).get_data() - : res_.get_resource_data_by_id(pe_resource_viewer::resource_cursor, group->Number, index).get_data(); - if(cursor.length() < 2 * sizeof(uint16_t)) - throw pe_exception("Incorrect resource cursor", pe_exception::resource_incorrect_cursor); - - //Here it is - two words in the very beginning of cursor data - direntry.HotspotX = *reinterpret_cast<const uint16_t*>(cursor.data()); - direntry.HotspotY = *reinterpret_cast<const uint16_t*>(cursor.data() + sizeof(uint16_t)); - - //Fill the rest data - direntry.SizeInBytes = group->SizeInBytes - 2 * sizeof(uint16_t); - direntry.ImageOffset = offset; - - //Add cursor header - cur_data.append(reinterpret_cast<const char*>(&direntry), sizeof(cursordirentry)); - - offset += direntry.SizeInBytes; - } - - //Return cursor count - return info->Count; -} - -//Returns cursor data by name and language (minimum checks of format correctness) -const std::string resource_cursor_icon_reader::get_cursor_by_name(uint32_t language, const std::wstring& name) const -{ - std::string ret; - - //Get resource by name and language - const std::string resource_data = res_.get_resource_data_by_name(language, pe_resource_viewer::resource_cursor_group, name).get_data(); - - //Create cursor headers - uint16_t cursor_count = format_cursor_headers(ret, resource_data, language); - - //Add cursor data - for(uint16_t i = 0; i != cursor_count; ++i) - { - const cursor_group* group = reinterpret_cast<const cursor_group*>(resource_data.data() + sizeof(cursor_header) + i * sizeof(cursor_group)); - ret += res_.get_resource_data_by_id(language, pe_resource_viewer::resource_cursor, group->Number).get_data().substr(2 * sizeof(uint16_t)); - } - - return ret; -} - -//Returns cursor data by name and index in language directory (instead of language) (minimum checks of format correctness) -const std::string resource_cursor_icon_reader::get_cursor_by_name(const std::wstring& name, uint32_t index) const -{ - std::string ret; - - //Get resource by name and index - const std::string resource_data = res_.get_resource_data_by_name(pe_resource_viewer::resource_cursor_group, name, index).get_data(); - - //Create cursor headers - uint16_t cursor_count = format_cursor_headers(ret, resource_data, 0, index); - - //Add cursor data - for(uint16_t i = 0; i != cursor_count; ++i) - { - const cursor_group* group = reinterpret_cast<const cursor_group*>(resource_data.data() + sizeof(cursor_header) + i * sizeof(cursor_group)); - ret += res_.get_resource_data_by_id(pe_resource_viewer::resource_cursor, group->Number, index).get_data().substr(2 * sizeof(uint16_t)); - } - - return ret; -} - -//Returns cursor data by ID and language (minimum checks of format correctness) -const std::string resource_cursor_icon_reader::get_cursor_by_id_lang(uint32_t language, uint32_t id) const -{ - std::string ret; - - //Get resource by ID and language - const std::string resource_data = res_.get_resource_data_by_id(language, pe_resource_viewer::resource_cursor_group, id).get_data(); - - //Create cursor headers - uint16_t cursor_count = format_cursor_headers(ret, resource_data, language); - - //Add cursor data - for(uint16_t i = 0; i != cursor_count; ++i) - { - const cursor_group* group = reinterpret_cast<const cursor_group*>(resource_data.data() + sizeof(cursor_header) + i * sizeof(cursor_group)); - ret += res_.get_resource_data_by_id(language, pe_resource_viewer::resource_cursor, group->Number).get_data().substr(2 * sizeof(uint16_t)); - } - - return ret; -} - -//Returns cursor data by ID and index in language directory (instead of language) (minimum checks of format correctness) -const std::string resource_cursor_icon_reader::get_cursor_by_id(uint32_t id, uint32_t index) const -{ - std::string ret; - - //Get resource by ID and index - const std::string resource_data = res_.get_resource_data_by_id(pe_resource_viewer::resource_cursor_group, id, index).get_data(); - - //Create cursor headers - uint16_t cursor_count = format_cursor_headers(ret, resource_data, 0, index); - - //Add cursor data - for(uint16_t i = 0; i != cursor_count; ++i) - { - const cursor_group* group = reinterpret_cast<const cursor_group*>(resource_data.data() + sizeof(cursor_header) + i * sizeof(cursor_group)); - ret += res_.get_resource_data_by_id(pe_resource_viewer::resource_cursor, group->Number, index).get_data().substr(2 * sizeof(uint16_t)); - } - - return ret; -} - -//Checks for cursor presence inside cursor group, fills cursor headers if found -bool resource_cursor_icon_reader::check_cursor_presence(const std::string& cursor_group_resource_data, uint32_t cursor_id, std::string& cur_header_data, const std::string& raw_cursor_data) -{ - //Check resource data length - if(cursor_group_resource_data.length() < sizeof(cursor_header)) - throw pe_exception("Incorrect resource cursor", pe_exception::resource_incorrect_cursor); - - const cursor_header* info = reinterpret_cast<const cursor_header*>(cursor_group_resource_data.data()); - - //Check resource data length - if(cursor_group_resource_data.length() < sizeof(cursor_header) + sizeof(cursor_group)) - throw pe_exception("Incorrect resource cursor", pe_exception::resource_incorrect_cursor); - - //Iterate over all cursors listed in cursor group - for(uint16_t i = 0; i != info->Count; ++i) - { - const cursor_group* group = reinterpret_cast<const cursor_group*>(cursor_group_resource_data.data() + sizeof(cursor_header) + i * sizeof(cursor_group)); - - if(group->Number == cursor_id) - { - //Reserve needed space to speed up a little - cur_header_data.reserve(sizeof(cursor_header) + sizeof(cursordirentry)); - //Write single-cursor cursor header - cursor_header new_header = *info; - new_header.Count = 1; - cur_header_data.append(reinterpret_cast<const char*>(&new_header), sizeof(cursor_header)); - - //Fill cursor info - cursordirentry direntry; - direntry.ColorCount = 0; //OK - direntry.Width = static_cast<uint8_t>(group->Width); - direntry.Height = static_cast<uint8_t>(group->Height) / 2; - direntry.Reserved = 0; - - if(raw_cursor_data.length() < 2 * sizeof(uint16_t)) - throw pe_exception("Incorrect resource cursor", pe_exception::resource_incorrect_cursor); - - //Here it is - two words in the very beginning of cursor data - direntry.HotspotX = *reinterpret_cast<const uint16_t*>(raw_cursor_data.data()); - direntry.HotspotY = *reinterpret_cast<const uint16_t*>(raw_cursor_data.data() + sizeof(uint16_t)); - - //Fill the rest data - direntry.SizeInBytes = group->SizeInBytes - 2 * sizeof(uint16_t); - direntry.ImageOffset = sizeof(cursor_header) + sizeof(cursordirentry); - - //Add cursor header - cur_header_data.append(reinterpret_cast<const char*>(&direntry), sizeof(cursordirentry)); - - return true; - } - } - - return false; -} - -//Looks up cursor group by cursor id and returns full cursor headers if found -const std::string resource_cursor_icon_reader::lookup_cursor_group_data_by_cursor(uint32_t cursor_id, uint32_t language, const std::string& raw_cursor_data) const -{ - std::string cursor_header_data; - - { - //List all ID-resources - pe_resource_viewer::resource_id_list ids(res_.list_resource_ids(pe_resource_viewer::resource_cursor_group)); - - for(pe_resource_viewer::resource_id_list::const_iterator it = ids.begin(); it != ids.end(); ++it) - { - pe_resource_viewer::resource_language_list group_languages(res_.list_resource_languages(pe_resource_viewer::resource_cursor_group, *it)); - if(std::find(group_languages.begin(), group_languages.end(), language) != group_languages.end() - && check_cursor_presence(res_.get_resource_data_by_id(language, pe_resource_viewer::resource_cursor_group, *it).get_data(), cursor_id, cursor_header_data, raw_cursor_data)) - return cursor_header_data; - } - } - - { - //List all named resources - pe_resource_viewer::resource_name_list names(res_.list_resource_names(pe_resource_viewer::resource_cursor_group)); - for(pe_resource_viewer::resource_name_list::const_iterator it = names.begin(); it != names.end(); ++it) - { - pe_resource_viewer::resource_language_list group_languages(res_.list_resource_languages(pe_resource_viewer::resource_cursor_group, *it)); - if(std::find(group_languages.begin(), group_languages.end(), language) != group_languages.end() - && check_cursor_presence(res_.get_resource_data_by_name(language, pe_resource_viewer::resource_cursor_group, *it).get_data(), cursor_id, cursor_header_data, raw_cursor_data)) - return cursor_header_data; - } - } - - throw pe_exception("No cursor group find for requested icon", pe_exception::no_cursor_group_found); -} -} diff --git a/tools/pe_bliss/resource_cursor_icon_reader.h b/tools/pe_bliss/resource_cursor_icon_reader.h deleted file mode 100644 index e34fff419b..0000000000 --- a/tools/pe_bliss/resource_cursor_icon_reader.h +++ /dev/null @@ -1,84 +0,0 @@ -/*************************************************************************/ -/* Copyright (c) 2015 dx, http://kaimi.ru */ -/* */ -/* Permission is hereby granted, free of charge, to any person */ -/* obtaining a copy of this software and associated documentation */ -/* files (the "Software"), to deal in the Software without */ -/* restriction, including without limitation the rights to use, */ -/* copy, modify, merge, publish, distribute, sublicense, and/or */ -/* sell copies of the Software, and to permit persons to whom the */ -/* Software is furnished to do so, subject to the following conditions: */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#pragma once -#include <string> -#include "stdint_defs.h" - -namespace pe_bliss -{ -class pe_resource_viewer; - -class resource_cursor_icon_reader -{ -public: - resource_cursor_icon_reader(const pe_resource_viewer& res); - - //Returns single icon data by ID and language (minimum checks of format correctness) - const std::string get_single_icon_by_id_lang(uint32_t language, uint32_t id) const; - //Returns single icon data by ID and index in language directory (instead of language) (minimum checks of format correctness) - const std::string get_single_icon_by_id(uint32_t id, uint32_t index = 0) const; - - //Returns icon data of group of icons by name and language (minimum checks of format correctness) - const std::string get_icon_by_name(uint32_t language, const std::wstring& icon_group_name) const; - //Returns icon data of group of icons by name and index in language directory (instead of language) (minimum checks of format correctness) - const std::string get_icon_by_name(const std::wstring& icon_group_name, uint32_t index = 0) const; - //Returns icon data of group of icons by ID and language (minimum checks of format correctness) - const std::string get_icon_by_id_lang(uint32_t language, uint32_t icon_group_id) const; - //Returns icon data of group of icons by ID and index in language directory (instead of language) (minimum checks of format correctness) - const std::string get_icon_by_id(uint32_t icon_group_id, uint32_t index = 0) const; - - //Returns single cursor data by ID and language (minimum checks of format correctness) - const std::string get_single_cursor_by_id_lang(uint32_t language, uint32_t id) const; - //Returns single cursor data by ID and index in language directory (instead of language) (minimum checks of format correctness) - const std::string get_single_cursor_by_id(uint32_t id, uint32_t index = 0) const; - - //Returns cursor data by name and language (minimum checks of format correctness) - const std::string get_cursor_by_name(uint32_t language, const std::wstring& cursor_group_name) const; - //Returns cursor data by name and index in language directory (instead of language) (minimum checks of format correctness) - const std::string get_cursor_by_name(const std::wstring& cursor_group_name, uint32_t index = 0) const; - //Returns cursor data by ID and language (minimum checks of format correctness) - const std::string get_cursor_by_id_lang(uint32_t language, uint32_t cursor_group_id) const; - //Returns cursor data by ID and index in language directory (instead of language) (minimum checks of format correctness) - const std::string get_cursor_by_id(uint32_t cursor_group_id, uint32_t index = 0) const; - -private: - const pe_resource_viewer& res_; - - //Helper function of creating icon headers from ICON_GROUP resource data - //Returns icon count - static uint16_t format_icon_headers(std::string& ico_data, const std::string& resource_data); - - //Helper function of creating cursor headers from CURSOR_GROUP resource data - //Returns cursor count - uint16_t format_cursor_headers(std::string& cur_data, const std::string& resource_data, uint32_t language, uint32_t index = 0xFFFFFFFF) const; - - //Looks up icon group by icon id and returns full icon headers if found - const std::string lookup_icon_group_data_by_icon(uint32_t icon_id, uint32_t language) const; - //Checks for icon presence inside icon group, fills icon headers if found - static bool check_icon_presence(const std::string& icon_group_resource_data, uint32_t icon_id, std::string& ico_data); - - //Looks up cursor group by cursor id and returns full cursor headers if found - const std::string lookup_cursor_group_data_by_cursor(uint32_t cursor_id, uint32_t language, const std::string& raw_cursor_data) const; - //Checks for cursor presence inside cursor group, fills cursor headers if found - static bool check_cursor_presence(const std::string& icon_group_resource_data, uint32_t cursor_id, std::string& cur_header_data, const std::string& raw_cursor_data); -}; -} diff --git a/tools/pe_bliss/resource_cursor_icon_writer.cpp b/tools/pe_bliss/resource_cursor_icon_writer.cpp deleted file mode 100644 index 2f1c4363c4..0000000000 --- a/tools/pe_bliss/resource_cursor_icon_writer.cpp +++ /dev/null @@ -1,447 +0,0 @@ -/*************************************************************************/ -/* Copyright (c) 2015 dx, http://kaimi.ru */ -/* */ -/* Permission is hereby granted, free of charge, to any person */ -/* obtaining a copy of this software and associated documentation */ -/* files (the "Software"), to deal in the Software without */ -/* restriction, including without limitation the rights to use, */ -/* copy, modify, merge, publish, distribute, sublicense, and/or */ -/* sell copies of the Software, and to permit persons to whom the */ -/* Software is furnished to do so, subject to the following conditions: */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#include <algorithm> -#include <string.h> -#include "resource_cursor_icon_writer.h" - -namespace pe_bliss -{ -using namespace pe_win; - -resource_cursor_icon_writer::resource_cursor_icon_writer(pe_resource_manager& res) - :res_(res) -{} - -//Add icon helper -void resource_cursor_icon_writer::add_icon(const std::string& icon_file, const resource_data_info* group_icon_info /* or zero */, resource_directory_entry& new_icon_group_entry, const resource_directory::entry_finder& finder, uint32_t language, icon_place_mode mode, uint32_t codepage, uint32_t timestamp) -{ - //Check icon for correctness - if(icon_file.length() < sizeof(ico_header)) - throw pe_exception("Incorrect resource icon", pe_exception::resource_incorrect_icon); - - const ico_header* icon_header = reinterpret_cast<const ico_header*>(&icon_file[0]); - - unsigned long size_of_headers = sizeof(ico_header) + icon_header->Count * sizeof(icondirentry); - if(icon_file.length() < size_of_headers || icon_header->Count == 0) - throw pe_exception("Incorrect resource icon", pe_exception::resource_incorrect_icon); - - //Enumerate all icons in file - for(uint16_t i = 0; i != icon_header->Count; ++i) - { - //Check icon entries - const icondirentry* icon_entry = reinterpret_cast<const icondirentry*>(&icon_file[sizeof(ico_header) + i * sizeof(icondirentry)]); - if(icon_entry->SizeInBytes == 0 - || icon_entry->ImageOffset < size_of_headers - || !pe_utils::is_sum_safe(icon_entry->ImageOffset, icon_entry->SizeInBytes) - || icon_entry->ImageOffset + icon_entry->SizeInBytes > icon_file.length()) - throw pe_exception("Incorrect resource icon", pe_exception::resource_incorrect_icon); - } - - std::string icon_group_data; - ico_header* info = 0; - - if(group_icon_info) - { - //If icon group already exists - { - icon_group_data = group_icon_info->get_data(); - codepage = group_icon_info->get_codepage(); //Don't change codepage of icon group entry - } - - //Check resource data size - if(icon_group_data.length() < sizeof(ico_header)) - throw pe_exception("Incorrect resource icon", pe_exception::resource_incorrect_icon); - - //Get icon header - info = reinterpret_cast<ico_header*>(&icon_group_data[0]); - - //Check resource data size - if(icon_group_data.length() < sizeof(ico_header) + info->Count * sizeof(icon_group)) - throw pe_exception("Incorrect resource icon", pe_exception::resource_incorrect_icon); - - icon_group_data.resize(sizeof(ico_header) + (info->Count + icon_header->Count) * sizeof(icon_group)); - info = reinterpret_cast<ico_header*>(&icon_group_data[0]); //In case if memory was reallocated - } - else //Entry not found - icon group doesn't exist - { - icon_group_data.resize(sizeof(ico_header) + icon_header->Count * sizeof(icon_group)); - memcpy(&icon_group_data[0], icon_header, sizeof(ico_header)); - } - - //Search for available icon IDs - std::vector<uint16_t> icon_id_list(get_icon_or_cursor_free_id_list(pe_resource_viewer::resource_icon, mode, icon_header->Count)); - - //Enumerate all icons in file - for(uint16_t i = 0; i != icon_header->Count; ++i) - { - const icondirentry* icon_entry = reinterpret_cast<const icondirentry*>(&icon_file[sizeof(ico_header) + i * sizeof(icondirentry)]); - icon_group group = {0}; - - //Fill icon resource header - group.BitCount = icon_entry->BitCount; - group.ColorCount = icon_entry->ColorCount; - group.Height = icon_entry->Height; - group.Planes = icon_entry->Planes; - group.Reserved = icon_entry->Reserved; - group.SizeInBytes = icon_entry->SizeInBytes; - group.Width = icon_entry->Width; - group.Number = icon_id_list.at(i); - - memcpy(&icon_group_data[sizeof(ico_header) + ((info ? info->Count : 0) + i) * sizeof(icon_group)], &group, sizeof(group)); - - //Add icon to resources - resource_directory_entry new_entry; - new_entry.set_id(group.Number); - res_.add_resource(icon_file.substr(icon_entry->ImageOffset, icon_entry->SizeInBytes), pe_resource_viewer::resource_icon, new_entry, resource_directory::entry_finder(group.Number), language, codepage, timestamp); - } - - if(info) - info->Count += icon_header->Count; //Increase icon count, if we're adding icon to existing group - - { - //Add or replace icon group data entry - res_.add_resource(icon_group_data, pe_resource_viewer::resource_icon_group, new_icon_group_entry, finder, language, codepage, timestamp); - } -} - -//Returns free icon or cursor ID list depending on icon_place_mode -const std::vector<uint16_t> resource_cursor_icon_writer::get_icon_or_cursor_free_id_list(pe_resource_viewer::resource_type type, icon_place_mode mode, uint32_t count) -{ - //Search for available icon/cursor IDs - std::vector<uint16_t> icon_cursor_id_list; - - try - { - //If any icon exists - //List icon IDs - std::vector<uint32_t> id_list(res_.list_resource_ids(type)); - std::sort(id_list.begin(), id_list.end()); - - //If we are placing icon on free spaces - //I.e., icon IDs 1, 3, 4, 7, 8 already exist - //We'll place five icons on IDs 2, 5, 6, 9, 10 - if(mode != icon_place_after_max_icon_id) - { - if(!id_list.empty()) - { - //Determine and list free icon IDs - for(std::vector<uint32_t>::const_iterator it = id_list.begin(); it != id_list.end(); ++it) - { - if(it == id_list.begin()) - { - if(*it > 1) - { - for(uint16_t i = 1; i != *it; ++i) - { - icon_cursor_id_list.push_back(i); - if(icon_cursor_id_list.size() == count) - break; - } - } - } - else if(*(it - 1) - *it > 1) - { - for(uint16_t i = static_cast<uint16_t>(*(it - 1) + 1); i != static_cast<uint16_t>(*it); ++i) - { - icon_cursor_id_list.push_back(i); - if(icon_cursor_id_list.size() == count) - break; - } - } - - if(icon_cursor_id_list.size() == count) - break; - } - } - } - - uint32_t max_id = id_list.empty() ? 0 : *std::max_element(id_list.begin(), id_list.end()); - for(uint32_t i = static_cast<uint32_t>(icon_cursor_id_list.size()); i != count; ++i) - icon_cursor_id_list.push_back(static_cast<uint16_t>(++max_id)); - } - catch(const pe_exception&) //Entry not found - { - for(uint16_t i = 1; i != count + 1; ++i) - icon_cursor_id_list.push_back(i); - } - - return icon_cursor_id_list; -} - -//Add cursor helper -void resource_cursor_icon_writer::add_cursor(const std::string& cursor_file, const resource_data_info* group_cursor_info /* or zero */, resource_directory_entry& new_cursor_group_entry, const resource_directory::entry_finder& finder, uint32_t language, icon_place_mode mode, uint32_t codepage, uint32_t timestamp) -{ - //Check cursor for correctness - if(cursor_file.length() < sizeof(cursor_header)) - throw pe_exception("Incorrect resource cursor", pe_exception::resource_incorrect_cursor); - - const cursor_header* cur_header = reinterpret_cast<const cursor_header*>(&cursor_file[0]); - - unsigned long size_of_headers = sizeof(cursor_header) + cur_header->Count * sizeof(cursordirentry); - if(cursor_file.length() < size_of_headers || cur_header->Count == 0) - throw pe_exception("Incorrect resource cursor", pe_exception::resource_incorrect_cursor); - - //Enumerate all cursors in file - for(uint16_t i = 0; i != cur_header->Count; ++i) - { - //Check cursor entries - const cursordirentry* cursor_entry = reinterpret_cast<const cursordirentry*>(&cursor_file[sizeof(cursor_header) + i * sizeof(cursordirentry)]); - if(cursor_entry->SizeInBytes == 0 - || cursor_entry->ImageOffset < size_of_headers - || !pe_utils::is_sum_safe(cursor_entry->ImageOffset, cursor_entry->SizeInBytes) - || cursor_entry->ImageOffset + cursor_entry->SizeInBytes > cursor_file.length()) - throw pe_exception("Incorrect resource cursor", pe_exception::resource_incorrect_cursor); - } - - std::string cursor_group_data; - cursor_header* info = 0; - - if(group_cursor_info) - { - //If cursor group already exists - { - cursor_group_data = group_cursor_info->get_data(); - codepage = group_cursor_info->get_codepage(); //Don't change codepage of cursor group entry - } - - //Check resource data size - if(cursor_group_data.length() < sizeof(cursor_header)) - throw pe_exception("Incorrect resource cursor", pe_exception::resource_incorrect_cursor); - - //Get cursor header - info = reinterpret_cast<cursor_header*>(&cursor_group_data[0]); - - //Check resource data size - if(cursor_group_data.length() < sizeof(cursor_header) + info->Count * sizeof(cursor_group)) - throw pe_exception("Incorrect resource cursor", pe_exception::resource_incorrect_cursor); - - cursor_group_data.resize(sizeof(cursor_header) + (info->Count + cur_header->Count) * sizeof(cursor_group)); - info = reinterpret_cast<cursor_header*>(&cursor_group_data[0]); //In case if memory was reallocated - } - else //Entry not found - cursor group doesn't exist - { - cursor_group_data.resize(sizeof(cursor_header) + cur_header->Count * sizeof(cursor_group)); - memcpy(&cursor_group_data[0], cur_header, sizeof(cursor_header)); - } - - //Search for available cursor IDs - std::vector<uint16_t> cursor_id_list(get_icon_or_cursor_free_id_list(pe_resource_viewer::resource_cursor, mode, cur_header->Count)); - - //Enumerate all cursors in file - for(uint16_t i = 0; i != cur_header->Count; ++i) - { - const cursordirentry* cursor_entry = reinterpret_cast<const cursordirentry*>(&cursor_file[sizeof(cursor_header) + i * sizeof(cursordirentry)]); - cursor_group group = {0}; - - //Fill cursor resource header - group.Height = cursor_entry->Height * 2; - group.SizeInBytes = cursor_entry->SizeInBytes + 2 * sizeof(uint16_t) /* hotspot coordinates */; - group.Width = cursor_entry->Width; - group.Number = cursor_id_list.at(i); - - memcpy(&cursor_group_data[sizeof(cursor_header) + ((info ? info->Count : 0) + i) * sizeof(cursor_group)], &group, sizeof(group)); - - //Add cursor to resources - resource_directory_entry new_entry; - new_entry.set_id(group.Number); - - //Fill resource data (two WORDs for hotspot of cursor, and cursor bitmap data) - std::string cur_data; - cur_data.resize(sizeof(uint16_t) * 2); - memcpy(&cur_data[0], &cursor_entry->HotspotX, sizeof(uint16_t)); - memcpy(&cur_data[sizeof(uint16_t)], &cursor_entry->HotspotY, sizeof(uint16_t)); - cur_data.append(cursor_file.substr(cursor_entry->ImageOffset, cursor_entry->SizeInBytes)); - - res_.add_resource(cur_data, pe_resource_viewer::resource_cursor, new_entry, resource_directory::entry_finder(group.Number), language, codepage, timestamp); - } - - if(info) - info->Count += cur_header->Count; //Increase cursor count, if we're adding cursor to existing group - - { - //Add or replace cursor group data entry - res_.add_resource(cursor_group_data, pe_resource_viewer::resource_cursor_group, new_cursor_group_entry, finder, language, codepage, timestamp); - } -} - -//Adds icon(s) from icon file data -//timestamp will be used for directories that will be added -//If icon group with name "icon_group_name" or ID "icon_group_id" already exists, it will be appended with new icon(s) -//(Codepage of icon group and icons will not be changed in this case) -//icon_place_mode determines, how new icon(s) will be placed -void resource_cursor_icon_writer::add_icon(const std::string& icon_file, const std::wstring& icon_group_name, uint32_t language, icon_place_mode mode, uint32_t codepage, uint32_t timestamp) -{ - resource_directory_entry new_icon_group_entry; - new_icon_group_entry.set_name(icon_group_name); - std::auto_ptr<resource_data_info> data_info; - - try - { - data_info.reset(new resource_data_info(res_.get_resource_data_by_name(language, pe_resource_viewer::resource_icon_group, icon_group_name))); - } - catch(const pe_exception&) //Entry not found - { - } - - add_icon(icon_file, data_info.get(), new_icon_group_entry, resource_directory::entry_finder(icon_group_name), language, mode, codepage, timestamp); -} - -void resource_cursor_icon_writer::add_icon(const std::string& icon_file, uint32_t icon_group_id, uint32_t language, icon_place_mode mode, uint32_t codepage, uint32_t timestamp) -{ - resource_directory_entry new_icon_group_entry; - new_icon_group_entry.set_id(icon_group_id); - std::auto_ptr<resource_data_info> data_info; - - try - { - data_info.reset(new resource_data_info(res_.get_resource_data_by_id(language, pe_resource_viewer::resource_icon_group, icon_group_id))); - } - catch(const pe_exception&) //Entry not found - { - } - - add_icon(icon_file, data_info.get(), new_icon_group_entry, resource_directory::entry_finder(icon_group_id), language, mode, codepage, timestamp); -} - -//Adds cursor(s) from cursor file data -//timestamp will be used for directories that will be added -//If cursor group with name "cursor_group_name" or ID "cursor_group_id" already exists, it will be appended with new cursor(s) -//(Codepage of cursor group and cursors will not be changed in this case) -//icon_place_mode determines, how new cursor(s) will be placed -void resource_cursor_icon_writer::add_cursor(const std::string& cursor_file, const std::wstring& cursor_group_name, uint32_t language, icon_place_mode mode, uint32_t codepage, uint32_t timestamp) -{ - resource_directory_entry new_cursor_group_entry; - new_cursor_group_entry.set_name(cursor_group_name); - std::auto_ptr<resource_data_info> data_info; - - try - { - data_info.reset(new resource_data_info(res_.get_resource_data_by_name(language, pe_resource_viewer::resource_cursor_group, cursor_group_name))); - } - catch(const pe_exception&) //Entry not found - { - } - - add_cursor(cursor_file, data_info.get(), new_cursor_group_entry, resource_directory::entry_finder(cursor_group_name), language, mode, codepage, timestamp); -} - -void resource_cursor_icon_writer::add_cursor(const std::string& cursor_file, uint32_t cursor_group_id, uint32_t language, icon_place_mode mode, uint32_t codepage, uint32_t timestamp) -{ - resource_directory_entry new_cursor_group_entry; - new_cursor_group_entry.set_id(cursor_group_id); - std::auto_ptr<resource_data_info> data_info; - - try - { - data_info.reset(new resource_data_info(res_.get_resource_data_by_id(language, pe_resource_viewer::resource_cursor_group, cursor_group_id))); - } - catch(const pe_exception&) //Entry not found - { - } - - add_cursor(cursor_file, data_info.get(), new_cursor_group_entry, resource_directory::entry_finder(cursor_group_id), language, mode, codepage, timestamp); -} - -//Remove icon group helper -void resource_cursor_icon_writer::remove_icons_from_icon_group(const std::string& icon_group_data, uint32_t language) -{ - //Check resource data size - if(icon_group_data.length() < sizeof(ico_header)) - throw pe_exception("Incorrect resource icon", pe_exception::resource_incorrect_icon); - - //Get icon header - const ico_header* info = reinterpret_cast<const ico_header*>(icon_group_data.data()); - - uint16_t icon_count = info->Count; - - //Check resource data size - if(icon_group_data.length() < sizeof(ico_header) + icon_count * sizeof(icon_group)) - throw pe_exception("Incorrect resource icon", pe_exception::resource_incorrect_icon); - - //Remove icon data - for(uint16_t i = 0; i != icon_count; ++i) - { - const icon_group* group = reinterpret_cast<const icon_group*>(icon_group_data.data() + sizeof(ico_header) + i * sizeof(icon_group)); - res_.remove_resource(pe_resource_viewer::resource_icon, group->Number, language); - } -} - -//Remove cursor group helper -void resource_cursor_icon_writer::remove_cursors_from_cursor_group(const std::string& cursor_group_data, uint32_t language) -{ - //Check resource data size - if(cursor_group_data.length() < sizeof(cursor_header)) - throw pe_exception("Incorrect resource cursor", pe_exception::resource_incorrect_cursor); - - //Get icon header - const cursor_header* info = reinterpret_cast<const cursor_header*>(cursor_group_data.data()); - - uint16_t cursor_count = info->Count; - - //Check resource data size - if(cursor_group_data.length() < sizeof(cursor_header) + cursor_count * sizeof(cursor_group)) - throw pe_exception("Incorrect resource cursor", pe_exception::resource_incorrect_cursor); - - //Remove icon data - for(uint16_t i = 0; i != cursor_count; ++i) - { - const icon_group* group = reinterpret_cast<const icon_group*>(cursor_group_data.data() + sizeof(cursor_header) + i * sizeof(cursor_group)); - res_.remove_resource(pe_resource_viewer::resource_cursor, group->Number, language); - } -} - -//Removes cursor group and all its cursors by name/ID and language -bool resource_cursor_icon_writer::remove_cursor_group(const std::wstring& cursor_group_name, uint32_t language) -{ - //Get resource by name and language - const std::string data = res_.get_resource_data_by_name(language, pe_resource_viewer::resource_cursor_group, cursor_group_name).get_data(); - remove_cursors_from_cursor_group(data, language); - return res_.remove_resource(pe_resource_viewer::resource_cursor_group, cursor_group_name, language); -} - -//Removes cursor group and all its cursors by name/ID and language -bool resource_cursor_icon_writer::remove_cursor_group(uint32_t cursor_group_id, uint32_t language) -{ - //Get resource by name and language - const std::string data = res_.get_resource_data_by_id(language, pe_resource_viewer::resource_cursor_group, cursor_group_id).get_data(); - remove_cursors_from_cursor_group(data, language); - return res_.remove_resource(pe_resource_viewer::resource_cursor_group, cursor_group_id, language); -} - -//Removes icon group and all its icons by name/ID and language -bool resource_cursor_icon_writer::remove_icon_group(const std::wstring& icon_group_name, uint32_t language) -{ - //Get resource by name and language - const std::string data = res_.get_resource_data_by_name(language, pe_resource_viewer::resource_icon_group, icon_group_name).get_data(); - remove_icons_from_icon_group(data, language); - return res_.remove_resource(pe_resource_viewer::resource_icon_group, icon_group_name, language); -} - -//Removes icon group and all its icons by name/ID and language -bool resource_cursor_icon_writer::remove_icon_group(uint32_t icon_group_id, uint32_t language) -{ - //Get resource by name and language - const std::string data = res_.get_resource_data_by_id(language, pe_resource_viewer::resource_icon_group, icon_group_id).get_data(); - remove_icons_from_icon_group(data, language); - return res_.remove_resource(pe_resource_viewer::resource_icon_group, icon_group_id, language); -} -} diff --git a/tools/pe_bliss/resource_cursor_icon_writer.h b/tools/pe_bliss/resource_cursor_icon_writer.h deleted file mode 100644 index e73ac6a093..0000000000 --- a/tools/pe_bliss/resource_cursor_icon_writer.h +++ /dev/null @@ -1,94 +0,0 @@ -/*************************************************************************/ -/* Copyright (c) 2015 dx, http://kaimi.ru */ -/* */ -/* Permission is hereby granted, free of charge, to any person */ -/* obtaining a copy of this software and associated documentation */ -/* files (the "Software"), to deal in the Software without */ -/* restriction, including without limitation the rights to use, */ -/* copy, modify, merge, publish, distribute, sublicense, and/or */ -/* sell copies of the Software, and to permit persons to whom the */ -/* Software is furnished to do so, subject to the following conditions: */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#pragma once -#include <string> -#include <vector> -#include "stdint_defs.h" -#include "pe_resource_manager.h" - -namespace pe_bliss -{ -class pe_resource_manager; - -class resource_cursor_icon_writer -{ -public: - //Determines, how new icon(s) or cursor(s) will be placed - enum icon_place_mode - { - icon_place_after_max_icon_id, //Icon(s) will be placed after all existing - icon_place_free_ids //New icon(s) will take all free IDs between existing icons - }; - -public: - resource_cursor_icon_writer(pe_resource_manager& res); - - //Removes icon group and all its icons by name/ID and language - bool remove_icon_group(const std::wstring& icon_group_name, uint32_t language); - bool remove_icon_group(uint32_t icon_group_id, uint32_t language); - - //Adds icon(s) from icon file data - //timestamp will be used for directories that will be added - //If icon group with name "icon_group_name" or ID "icon_group_id" already exists, it will be appended with new icon(s) - //(Codepage of icon group and icons will not be changed in this case) - //icon_place_mode determines, how new icon(s) will be placed - void add_icon(const std::string& icon_file, - const std::wstring& icon_group_name, - uint32_t language, icon_place_mode mode = icon_place_after_max_icon_id, - uint32_t codepage = 0, uint32_t timestamp = 0); - - void add_icon(const std::string& icon_file, - uint32_t icon_group_id, - uint32_t language, icon_place_mode mode = icon_place_after_max_icon_id, - uint32_t codepage = 0, uint32_t timestamp = 0); - - //Removes cursor group and all its cursors by name/ID and language - bool remove_cursor_group(const std::wstring& cursor_group_name, uint32_t language); - bool remove_cursor_group(uint32_t cursor_group_id, uint32_t language); - - //Adds cursor(s) from cursor file data - //timestamp will be used for directories that will be added - //If cursor group with name "cursor_group_name" or ID "cursor_group_id" already exists, it will be appended with new cursor(s) - //(Codepage of cursor group and cursors will not be changed in this case) - //icon_place_mode determines, how new cursor(s) will be placed - void add_cursor(const std::string& cursor_file, const std::wstring& cursor_group_name, uint32_t language, icon_place_mode mode = icon_place_after_max_icon_id, uint32_t codepage = 0, uint32_t timestamp = 0); - void add_cursor(const std::string& cursor_file, uint32_t cursor_group_id, uint32_t language, icon_place_mode mode = icon_place_after_max_icon_id, uint32_t codepage = 0, uint32_t timestamp = 0); - -private: - pe_resource_manager& res_; - - //Add icon helper - void add_icon(const std::string& icon_file, const resource_data_info* group_icon_info /* or zero */, resource_directory_entry& new_icon_group_entry, const resource_directory::entry_finder& finder, uint32_t language, icon_place_mode mode, uint32_t codepage, uint32_t timestamp); - - //Remove icon group helper - void remove_icons_from_icon_group(const std::string& icon_group_data, uint32_t language); - - //Add cursor helper - void add_cursor(const std::string& cursor_file, const resource_data_info* group_cursor_info /* or zero */, resource_directory_entry& new_cursor_group_entry, const resource_directory::entry_finder& finder, uint32_t language, icon_place_mode mode, uint32_t codepage, uint32_t timestamp); - - //Remove cursor group helper - void remove_cursors_from_cursor_group(const std::string& cursor_group_data, uint32_t language); - - //Returns free icon or cursor ID list depending on icon_place_mode - const std::vector<uint16_t> get_icon_or_cursor_free_id_list(pe_resource_manager::resource_type type, icon_place_mode mode, uint32_t count); -}; -} diff --git a/tools/pe_bliss/resource_data_info.cpp b/tools/pe_bliss/resource_data_info.cpp deleted file mode 100644 index 75bb060eae..0000000000 --- a/tools/pe_bliss/resource_data_info.cpp +++ /dev/null @@ -1,48 +0,0 @@ -/*************************************************************************/ -/* Copyright (c) 2015 dx, http://kaimi.ru */ -/* */ -/* Permission is hereby granted, free of charge, to any person */ -/* obtaining a copy of this software and associated documentation */ -/* files (the "Software"), to deal in the Software without */ -/* restriction, including without limitation the rights to use, */ -/* copy, modify, merge, publish, distribute, sublicense, and/or */ -/* sell copies of the Software, and to permit persons to whom the */ -/* Software is furnished to do so, subject to the following conditions: */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#include "resource_data_info.h" -#include "pe_resource_viewer.h" - -namespace pe_bliss -{ -//Default constructor -resource_data_info::resource_data_info(const std::string& data, uint32_t codepage) - :data_(data), codepage_(codepage) -{} - -//Constructor from data -resource_data_info::resource_data_info(const resource_data_entry& data) - :data_(data.get_data()), codepage_(data.get_codepage()) -{} - -//Returns resource data -const std::string& resource_data_info::get_data() const -{ - return data_; -} - -//Returns resource codepage -uint32_t resource_data_info::get_codepage() const -{ - return codepage_; -} -} diff --git a/tools/pe_bliss/resource_data_info.h b/tools/pe_bliss/resource_data_info.h deleted file mode 100644 index e2275ebbf5..0000000000 --- a/tools/pe_bliss/resource_data_info.h +++ /dev/null @@ -1,48 +0,0 @@ -/*************************************************************************/ -/* Copyright (c) 2015 dx, http://kaimi.ru */ -/* */ -/* Permission is hereby granted, free of charge, to any person */ -/* obtaining a copy of this software and associated documentation */ -/* files (the "Software"), to deal in the Software without */ -/* restriction, including without limitation the rights to use, */ -/* copy, modify, merge, publish, distribute, sublicense, and/or */ -/* sell copies of the Software, and to permit persons to whom the */ -/* Software is furnished to do so, subject to the following conditions: */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#pragma once -#include <string> -#include "stdint_defs.h" - -namespace pe_bliss -{ -class resource_data_entry; - -//Class representing resource data -class resource_data_info -{ -public: - //Constructor from data - resource_data_info(const std::string& data, uint32_t codepage); - //Constructor from data - explicit resource_data_info(const resource_data_entry& data); - - //Returns resource data - const std::string& get_data() const; - //Returns resource codepage - uint32_t get_codepage() const; - -private: - std::string data_; - uint32_t codepage_; -}; -} diff --git a/tools/pe_bliss/resource_internal.h b/tools/pe_bliss/resource_internal.h deleted file mode 100644 index 64a5bf3903..0000000000 --- a/tools/pe_bliss/resource_internal.h +++ /dev/null @@ -1,34 +0,0 @@ -/*************************************************************************/ -/* Copyright (c) 2015 dx, http://kaimi.ru */ -/* */ -/* Permission is hereby granted, free of charge, to any person */ -/* obtaining a copy of this software and associated documentation */ -/* files (the "Software"), to deal in the Software without */ -/* restriction, including without limitation the rights to use, */ -/* copy, modify, merge, publish, distribute, sublicense, and/or */ -/* sell copies of the Software, and to permit persons to whom the */ -/* Software is furnished to do so, subject to the following conditions: */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#pragma once - -#define U16TEXT(t) reinterpret_cast<const unicode16_t*>( t ) - -#define StringFileInfo U16TEXT("S\0t\0r\0i\0n\0g\0F\0i\0l\0e\0I\0n\0f\0o\0\0") -#define SizeofStringFileInfo sizeof("S\0t\0r\0i\0n\0g\0F\0i\0l\0e\0I\0n\0f\0o\0\0") -#define VarFileInfo U16TEXT("V\0a\0r\0F\0i\0l\0e\0I\0n\0f\0o\0\0") -#define Translation U16TEXT("T\0r\0a\0n\0s\0l\0a\0t\0i\0o\0n\0\0") - -#define VarFileInfoAligned U16TEXT("V\0a\0r\0F\0i\0l\0e\0I\0n\0f\0o\0\0\0\0") -#define TranslationAligned U16TEXT("T\0r\0a\0n\0s\0l\0a\0t\0i\0o\0n\0\0\0\0") -#define SizeofVarFileInfoAligned sizeof("V\0a\0r\0F\0i\0l\0e\0I\0n\0f\0o\0\0\0\0") -#define SizeofTranslationAligned sizeof("T\0r\0a\0n\0s\0l\0a\0t\0i\0o\0n\0\0\0\0") diff --git a/tools/pe_bliss/resource_message_list_reader.cpp b/tools/pe_bliss/resource_message_list_reader.cpp deleted file mode 100644 index f2ea142bee..0000000000 --- a/tools/pe_bliss/resource_message_list_reader.cpp +++ /dev/null @@ -1,131 +0,0 @@ -/*************************************************************************/ -/* Copyright (c) 2015 dx, http://kaimi.ru */ -/* */ -/* Permission is hereby granted, free of charge, to any person */ -/* obtaining a copy of this software and associated documentation */ -/* files (the "Software"), to deal in the Software without */ -/* restriction, including without limitation the rights to use, */ -/* copy, modify, merge, publish, distribute, sublicense, and/or */ -/* sell copies of the Software, and to permit persons to whom the */ -/* Software is furnished to do so, subject to the following conditions: */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#include "resource_message_list_reader.h" -#include "pe_resource_viewer.h" - -namespace pe_bliss -{ -using namespace pe_win; - -resource_message_list_reader::resource_message_list_reader(const pe_resource_viewer& res) - :res_(res) -{} - -//Helper function of parsing message list table -const resource_message_list resource_message_list_reader::parse_message_list(const std::string& resource_data) -{ - resource_message_list ret; - - //Check resource data length - if(resource_data.length() < sizeof(message_resource_data)) - throw pe_exception("Incorrect resource message table", pe_exception::resource_incorrect_message_table); - - const message_resource_data* message_data = reinterpret_cast<const message_resource_data*>(resource_data.data()); - - //Check resource data length more carefully and some possible overflows - if(message_data->NumberOfBlocks >= pe_utils::max_dword / sizeof(message_resource_block) - || !pe_utils::is_sum_safe(message_data->NumberOfBlocks * sizeof(message_resource_block), sizeof(message_resource_data)) - || resource_data.length() < message_data->NumberOfBlocks * sizeof(message_resource_block) + sizeof(message_resource_data)) - throw pe_exception("Incorrect resource message table", pe_exception::resource_incorrect_message_table); - - //Iterate over all message resource blocks - for(unsigned long i = 0; i != message_data->NumberOfBlocks; ++i) - { - //Get block - const message_resource_block* block = - reinterpret_cast<const message_resource_block*>(resource_data.data() + sizeof(message_resource_data) - sizeof(message_resource_block) + sizeof(message_resource_block) * i); - - //Check resource data length and IDs - if(resource_data.length() < block->OffsetToEntries || block->LowId > block->HighId) - throw pe_exception("Incorrect resource message table", pe_exception::resource_incorrect_message_table); - - unsigned long current_pos = 0; - static const unsigned long size_of_entry_headers = 4; - //List all message resource entries in block - for(uint32_t curr_id = block->LowId; curr_id <= block->HighId; curr_id++) - { - //Check resource data length and some possible overflows - if(!pe_utils::is_sum_safe(block->OffsetToEntries, current_pos) - || !pe_utils::is_sum_safe(block->OffsetToEntries + current_pos, size_of_entry_headers) - || resource_data.length() < block->OffsetToEntries + current_pos + size_of_entry_headers) - throw pe_exception("Incorrect resource message table", pe_exception::resource_incorrect_message_table); - - //Get entry - const message_resource_entry* entry = reinterpret_cast<const message_resource_entry*>(resource_data.data() + block->OffsetToEntries + current_pos); - - //Check resource data length and entry length and some possible overflows - if(entry->Length < size_of_entry_headers - || !pe_utils::is_sum_safe(block->OffsetToEntries + current_pos, entry->Length) - || resource_data.length() < block->OffsetToEntries + current_pos + entry->Length - || entry->Length < size_of_entry_headers) - throw pe_exception("Incorrect resource message table", pe_exception::resource_incorrect_message_table); - - if(entry->Flags & message_resource_unicode) - { - //If string is UNICODE - //Check its length - if(entry->Length % 2) - throw pe_exception("Incorrect resource message table", pe_exception::resource_incorrect_message_table); - - //Add ID and string to message table -#ifdef PE_BLISS_WINDOWS - ret.insert(std::make_pair(curr_id, message_table_item( - std::wstring(reinterpret_cast<const wchar_t*>(resource_data.data() + block->OffsetToEntries + current_pos + size_of_entry_headers), - (entry->Length - size_of_entry_headers) / 2) - ))); -#else - ret.insert(std::make_pair(curr_id, message_table_item( - pe_utils::from_ucs2(u16string(reinterpret_cast<const unicode16_t*>(resource_data.data() + block->OffsetToEntries + current_pos + size_of_entry_headers), - (entry->Length - size_of_entry_headers) / 2)) - ))); -#endif - } - else - { - //If string is ANSI - //Add ID and string to message table - ret.insert(std::make_pair(curr_id, message_table_item( - std::string(resource_data.data() + block->OffsetToEntries + current_pos + size_of_entry_headers, - entry->Length - size_of_entry_headers) - ))); - } - - //Go to next entry - current_pos += entry->Length; - } - } - - return ret; -} - -//Returns message table data by ID and index in language directory (instead of language) -const resource_message_list resource_message_list_reader::get_message_table_by_id(uint32_t id, uint32_t index) const -{ - return parse_message_list(res_.get_resource_data_by_id(pe_resource_viewer::resource_message_table, id, index).get_data()); -} - -//Returns message table data by ID and language -const resource_message_list resource_message_list_reader::get_message_table_by_id_lang(uint32_t language, uint32_t id) const -{ - return parse_message_list(res_.get_resource_data_by_id(language, pe_resource_viewer::resource_message_table, id).get_data()); -} -} diff --git a/tools/pe_bliss/resource_message_list_reader.h b/tools/pe_bliss/resource_message_list_reader.h deleted file mode 100644 index a0ac96eb8c..0000000000 --- a/tools/pe_bliss/resource_message_list_reader.h +++ /dev/null @@ -1,49 +0,0 @@ -/*************************************************************************/ -/* Copyright (c) 2015 dx, http://kaimi.ru */ -/* */ -/* Permission is hereby granted, free of charge, to any person */ -/* obtaining a copy of this software and associated documentation */ -/* files (the "Software"), to deal in the Software without */ -/* restriction, including without limitation the rights to use, */ -/* copy, modify, merge, publish, distribute, sublicense, and/or */ -/* sell copies of the Software, and to permit persons to whom the */ -/* Software is furnished to do so, subject to the following conditions: */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#pragma once -#include "message_table.h" - -namespace pe_bliss -{ -class pe_resource_viewer; - -//ID; message_table_item -typedef std::map<uint32_t, message_table_item> resource_message_list; - -class resource_message_list_reader -{ -public: - resource_message_list_reader(const pe_resource_viewer& res); - - //Returns message table data by ID and language - const resource_message_list get_message_table_by_id_lang(uint32_t language, uint32_t id) const; - //Returns message table data by ID and index in language directory (instead of language) - const resource_message_list get_message_table_by_id(uint32_t id, uint32_t index = 0) const; - - //Helper function of parsing message list table - //resource_data - raw message table resource data - static const resource_message_list parse_message_list(const std::string& resource_data); - -private: - const pe_resource_viewer& res_; -}; -} diff --git a/tools/pe_bliss/resource_string_table_reader.cpp b/tools/pe_bliss/resource_string_table_reader.cpp deleted file mode 100644 index 8a51720e6a..0000000000 --- a/tools/pe_bliss/resource_string_table_reader.cpp +++ /dev/null @@ -1,109 +0,0 @@ -/*************************************************************************/ -/* Copyright (c) 2015 dx, http://kaimi.ru */ -/* */ -/* Permission is hereby granted, free of charge, to any person */ -/* obtaining a copy of this software and associated documentation */ -/* files (the "Software"), to deal in the Software without */ -/* restriction, including without limitation the rights to use, */ -/* copy, modify, merge, publish, distribute, sublicense, and/or */ -/* sell copies of the Software, and to permit persons to whom the */ -/* Software is furnished to do so, subject to the following conditions: */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#include "resource_string_table_reader.h" -#include "pe_resource_viewer.h" - -namespace pe_bliss -{ -resource_string_table_reader::resource_string_table_reader(const pe_resource_viewer& res) - :res_(res) -{} - -//Returns string table data by ID and index in language directory (instead of language) -const resource_string_list resource_string_table_reader::get_string_table_by_id(uint32_t id, uint32_t index) const -{ - return parse_string_list(id, res_.get_resource_data_by_id(pe_resource_viewer::resource_string, id, index).get_data()); -} - -//Returns string table data by ID and language -const resource_string_list resource_string_table_reader::get_string_table_by_id_lang(uint32_t language, uint32_t id) const -{ - return parse_string_list(id, res_.get_resource_data_by_id(language, pe_resource_viewer::resource_string, id).get_data()); -} - -//Helper function of parsing string list table -const resource_string_list resource_string_table_reader::parse_string_list(uint32_t id, const std::string& resource_data) -{ - resource_string_list ret; - - //16 is maximum count of strings in a string table - static const unsigned long max_string_list_entries = 16; - unsigned long passed_bytes = 0; - for(unsigned long i = 0; i != max_string_list_entries; ++i) - { - //Check resource data length - if(resource_data.length() < sizeof(uint16_t) + passed_bytes) - throw pe_exception("Incorrect resource string table", pe_exception::resource_incorrect_string_table); - - //Get string length - the first WORD - uint16_t string_length = *reinterpret_cast<const uint16_t*>(resource_data.data() + passed_bytes); - passed_bytes += sizeof(uint16_t); //WORD containing string length - - //Check resource data length again - if(resource_data.length() < string_length + passed_bytes) - throw pe_exception("Incorrect resource string table", pe_exception::resource_incorrect_string_table); - - if(string_length) - { - //Create and save string (UNICODE) -#ifdef PE_BLISS_WINDOWS - ret.insert( - std::make_pair(static_cast<uint16_t>(((id - 1) << 4) + i), //ID of string is calculated such way - std::wstring(reinterpret_cast<const wchar_t*>(resource_data.data() + passed_bytes), string_length))); -#else - ret.insert( - std::make_pair(static_cast<uint16_t>(((id - 1) << 4) + i), //ID of string is calculated such way - pe_utils::from_ucs2(u16string(reinterpret_cast<const unicode16_t*>(resource_data.data() + passed_bytes), string_length)))); -#endif - } - - //Go to next string - passed_bytes += string_length * 2; - } - - return ret; -} - -//Returns string from string table by ID and language -const std::wstring resource_string_table_reader::get_string_by_id_lang(uint32_t language, uint16_t id) const -{ - //List strings by string table id and language - const resource_string_list strings(get_string_table_by_id_lang(language, (id >> 4) + 1)); - resource_string_list::const_iterator it = strings.find(id); //Find string by id - if(it == strings.end()) - throw pe_exception("Resource string not found", pe_exception::resource_string_not_found); - - return (*it).second; -} - -//Returns string from string table by ID and index in language directory (instead of language) -const std::wstring resource_string_table_reader::get_string_by_id(uint16_t id, uint32_t index) const -{ - //List strings by string table id and index - const resource_string_list strings(get_string_table_by_id((id >> 4) + 1, index)); - resource_string_list::const_iterator it = strings.find(id); //Find string by id - if(it == strings.end()) - throw pe_exception("Resource string not found", pe_exception::resource_string_not_found); - - return (*it).second; -} -} diff --git a/tools/pe_bliss/resource_string_table_reader.h b/tools/pe_bliss/resource_string_table_reader.h deleted file mode 100644 index e3ded1da85..0000000000 --- a/tools/pe_bliss/resource_string_table_reader.h +++ /dev/null @@ -1,57 +0,0 @@ -/*************************************************************************/ -/* Copyright (c) 2015 dx, http://kaimi.ru */ -/* */ -/* Permission is hereby granted, free of charge, to any person */ -/* obtaining a copy of this software and associated documentation */ -/* files (the "Software"), to deal in the Software without */ -/* restriction, including without limitation the rights to use, */ -/* copy, modify, merge, publish, distribute, sublicense, and/or */ -/* sell copies of the Software, and to permit persons to whom the */ -/* Software is furnished to do so, subject to the following conditions: */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#pragma once -#include <string> -#include <map> -#include "stdint_defs.h" - -namespace pe_bliss -{ -class pe_resource_viewer; - -//ID; string -typedef std::map<uint16_t, std::wstring> resource_string_list; - -class resource_string_table_reader -{ -public: - resource_string_table_reader(const pe_resource_viewer& res); - -public: - //Returns string table data by ID and language - const resource_string_list get_string_table_by_id_lang(uint32_t language, uint32_t id) const; - //Returns string table data by ID and index in language directory (instead of language) - const resource_string_list get_string_table_by_id(uint32_t id, uint32_t index = 0) const; - //Returns string from string table by ID and language - const std::wstring get_string_by_id_lang(uint32_t language, uint16_t id) const; - //Returns string from string table by ID and index in language directory (instead of language) - const std::wstring get_string_by_id(uint16_t id, uint32_t index = 0) const; - -private: - const pe_resource_viewer& res_; - - //Helper function of parsing string list table - //Id of resource is needed to calculate string IDs correctly - //resource_data is raw string table resource data - static const resource_string_list parse_string_list(uint32_t id, const std::string& resource_data); -}; -} diff --git a/tools/pe_bliss/resource_version_info_reader.cpp b/tools/pe_bliss/resource_version_info_reader.cpp deleted file mode 100644 index 8ad44c6856..0000000000 --- a/tools/pe_bliss/resource_version_info_reader.cpp +++ /dev/null @@ -1,311 +0,0 @@ -/*************************************************************************/ -/* Copyright (c) 2015 dx, http://kaimi.ru */ -/* */ -/* Permission is hereby granted, free of charge, to any person */ -/* obtaining a copy of this software and associated documentation */ -/* files (the "Software"), to deal in the Software without */ -/* restriction, including without limitation the rights to use, */ -/* copy, modify, merge, publish, distribute, sublicense, and/or */ -/* sell copies of the Software, and to permit persons to whom the */ -/* Software is furnished to do so, subject to the following conditions: */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#include "resource_version_info_reader.h" -#include "utils.h" -#include "pe_exception.h" -#include "resource_internal.h" -#include "pe_resource_viewer.h" - -namespace pe_bliss -{ -using namespace pe_win; - -//Root version info block key value -const u16string resource_version_info_reader::version_info_key(U16TEXT("V\0S\0_\0V\0E\0R\0S\0I\0O\0N\0_\0I\0N\0F\0O\0\0")); - -resource_version_info_reader::resource_version_info_reader(const pe_resource_viewer& res) - :res_(res) -{} - -//Returns aligned version block value position -uint32_t resource_version_info_reader::get_version_block_value_pos(uint32_t base_pos, const unicode16_t* key) -{ - uint32_t string_length = static_cast<uint32_t>(u16string(key).length()); - uint32_t ret = pe_utils::align_up(static_cast<uint32_t>(sizeof(uint16_t) * 3 /* headers before Key data */ - + base_pos - + (string_length + 1 /* nullbyte */) * 2), - sizeof(uint32_t)); - - //Check possible overflows - if(ret < base_pos || ret < sizeof(uint16_t) * 3 || ret < (string_length + 1) * 2) - throw_incorrect_version_info(); - - return ret; -} - -//Returns aligned version block first child position -uint32_t resource_version_info_reader::get_version_block_first_child_pos(uint32_t base_pos, uint32_t value_length, const unicode16_t* key) -{ - uint32_t string_length = static_cast<uint32_t>(u16string(key).length()); - uint32_t ret = pe_utils::align_up(static_cast<uint32_t>(sizeof(uint16_t) * 3 /* headers before Key data */ - + base_pos - + (string_length + 1 /* nullbyte */) * 2), - sizeof(uint32_t)) - + pe_utils::align_up(value_length, sizeof(uint32_t)); - - //Check possible overflows - if(ret < base_pos || ret < value_length || ret < sizeof(uint16_t) * 3 || ret < (string_length + 1) * 2) - throw_incorrect_version_info(); - - return ret; -} - -//Throws an exception (id = resource_incorrect_version_info) -void resource_version_info_reader::throw_incorrect_version_info() -{ - throw pe_exception("Incorrect resource version info", pe_exception::resource_incorrect_version_info); -} - -//Returns full version information: -//file_version_info: versions and file info -//lang_string_values_map: map of version info strings with encodings -//translation_values_map: map of translations -const file_version_info resource_version_info_reader::get_version_info(lang_string_values_map& string_values, translation_values_map& translations, const std::string& resource_data) const -{ - //Fixed file version info - file_version_info ret; - - //Check resource data length - if(resource_data.length() < sizeof(version_info_block)) - throw_incorrect_version_info(); - - //Root version info block - const version_info_block* root_block = reinterpret_cast<const version_info_block*>(resource_data.data()); - - //Check root block key for null-termination and its name - if(!pe_utils::is_null_terminated(root_block->Key, resource_data.length() - sizeof(uint16_t) * 3 /* headers before Key data */) - || version_info_key != reinterpret_cast<const unicode16_t*>(root_block->Key)) - throw_incorrect_version_info(); - - //If file has fixed version info - if(root_block->ValueLength) - { - //Get root block value position - uint32_t value_pos = get_version_block_value_pos(0, reinterpret_cast<const unicode16_t*>(root_block->Key)); - //Check value length - if(resource_data.length() < value_pos + sizeof(vs_fixedfileinfo)) - throw_incorrect_version_info(); - - //Get VS_FIXEDFILEINFO structure pointer - const vs_fixedfileinfo* file_info = reinterpret_cast<const vs_fixedfileinfo*>(resource_data.data() + value_pos); - //Check its signature and some other fields - if(file_info->dwSignature != vs_ffi_signature || file_info->dwStrucVersion != vs_ffi_strucversion) //Don't check if file_info->dwFileFlagsMask == VS_FFI_FILEFLAGSMASK - throw_incorrect_version_info(); - - //Save fixed version info - ret = file_version_info(*file_info); - } - - //Iterate over child elements of VS_VERSIONINFO (StringFileInfo or VarFileInfo) - for(uint32_t child_pos = get_version_block_first_child_pos(0, root_block->ValueLength, reinterpret_cast<const unicode16_t*>(root_block->Key)); - child_pos < root_block->Length;) - { - //Check block position - if(!pe_utils::is_sum_safe(child_pos, sizeof(version_info_block)) - || resource_data.length() < child_pos + sizeof(version_info_block)) - throw_incorrect_version_info(); - - //Get VERSION_INFO_BLOCK structure pointer - const version_info_block* block = reinterpret_cast<const version_info_block*>(resource_data.data() + child_pos); - - //Check its length - if(block->Length == 0) - throw_incorrect_version_info(); - - //Check block key for null-termination - if(!pe_utils::is_null_terminated(block->Key, resource_data.length() - child_pos - sizeof(uint16_t) * 3 /* headers before Key data */)) - throw_incorrect_version_info(); - - u16string info_type(reinterpret_cast<const unicode16_t*>(block->Key)); - //If we encountered StringFileInfo... - if(info_type == StringFileInfo) - { - //Enumerate all string tables - for(uint32_t string_table_pos = get_version_block_first_child_pos(child_pos, block->ValueLength, reinterpret_cast<const unicode16_t*>(block->Key)); - string_table_pos - child_pos < block->Length;) - { - //Check string table block position - if(resource_data.length() < string_table_pos + sizeof(version_info_block)) - throw_incorrect_version_info(); - - //Get VERSION_INFO_BLOCK structure pointer for string table - const version_info_block* string_table = reinterpret_cast<const version_info_block*>(resource_data.data() + string_table_pos); - - //Check its length - if(string_table->Length == 0) - throw_incorrect_version_info(); - - //Check string table key for null-termination - if(!pe_utils::is_null_terminated(string_table->Key, resource_data.length() - string_table_pos - sizeof(uint16_t) * 3 /* headers before Key data */)) - throw_incorrect_version_info(); - - string_values_map new_values; - - //Enumerate all strings in the string table - for(uint32_t string_pos = get_version_block_first_child_pos(string_table_pos, string_table->ValueLength, reinterpret_cast<const unicode16_t*>(string_table->Key)); - string_pos - string_table_pos < string_table->Length;) - { - //Check string block position - if(resource_data.length() < string_pos + sizeof(version_info_block)) - throw_incorrect_version_info(); - - //Get VERSION_INFO_BLOCK structure pointer for string block - const version_info_block* string_block = reinterpret_cast<const version_info_block*>(resource_data.data() + string_pos); - - //Check its length - if(string_block->Length == 0) - throw_incorrect_version_info(); - - //Check string block key for null-termination - if(!pe_utils::is_null_terminated(string_block->Key, resource_data.length() - string_pos - sizeof(uint16_t) * 3 /* headers before Key data */)) - throw_incorrect_version_info(); - - u16string data; - //If string block has value - if(string_block->ValueLength != 0) - { - //Get value position - uint32_t value_pos = get_version_block_value_pos(string_pos, reinterpret_cast<const unicode16_t*>(string_block->Key)); - //Check it - if(resource_data.length() < value_pos + string_block->ValueLength) - throw pe_exception("Incorrect resource version info", pe_exception::resource_incorrect_version_info); - - //Get UNICODE string value - data = u16string(reinterpret_cast<const unicode16_t*>(resource_data.data() + value_pos), string_block->ValueLength); - pe_utils::strip_nullbytes(data); - } - - //Save name-value pair -#ifdef PE_BLISS_WINDOWS - new_values.insert(std::make_pair(reinterpret_cast<const unicode16_t*>(string_block->Key), data)); -#else - new_values.insert(std::make_pair(pe_utils::from_ucs2(reinterpret_cast<const unicode16_t*>(string_block->Key)), - pe_utils::from_ucs2(data))); -#endif - - //Navigate to next string block - string_pos += pe_utils::align_up(string_block->Length, sizeof(uint32_t)); - } - -#ifdef PE_BLISS_WINDOWS - string_values.insert(std::make_pair(reinterpret_cast<const unicode16_t*>(string_table->Key), new_values)); -#else - string_values.insert(std::make_pair(pe_utils::from_ucs2(reinterpret_cast<const unicode16_t*>(string_table->Key)), new_values)); -#endif - - //Navigate to next string table block - string_table_pos += pe_utils::align_up(string_table->Length, sizeof(uint32_t)); - } - } - else if(info_type == VarFileInfo) //If we encountered VarFileInfo - { - for(uint32_t var_table_pos = get_version_block_first_child_pos(child_pos, block->ValueLength, reinterpret_cast<const unicode16_t*>(block->Key)); - var_table_pos - child_pos < block->Length;) - { - //Check var block position - if(resource_data.length() < var_table_pos + sizeof(version_info_block)) - throw_incorrect_version_info(); - - //Get VERSION_INFO_BLOCK structure pointer for var block - const version_info_block* var_table = reinterpret_cast<const version_info_block*>(resource_data.data() + var_table_pos); - - //Check its length - if(var_table->Length == 0) - throw_incorrect_version_info(); - - //Check its key for null-termination - if(!pe_utils::is_null_terminated(var_table->Key, resource_data.length() - var_table_pos - sizeof(uint16_t) * 3 /* headers before Key data */)) - throw_incorrect_version_info(); - - //If block is "Translation" (actually, there's no other types possible in VarFileInfo) and it has value - if(u16string(reinterpret_cast<const unicode16_t*>(var_table->Key)) == Translation && var_table->ValueLength) - { - //Get its value position - uint32_t value_pos = get_version_block_value_pos(var_table_pos, reinterpret_cast<const unicode16_t*>(var_table->Key)); - //Cherck value length - if(resource_data.length() < value_pos + var_table->ValueLength) - throw_incorrect_version_info(); - - //Get list of translations: pairs of LANGUAGE_ID - CODEPAGE_ID - for(unsigned long i = 0; i < var_table->ValueLength; i += sizeof(uint16_t) * 2) - { - //Pair of WORDs - uint16_t lang_id = *reinterpret_cast<const uint16_t*>(resource_data.data() + value_pos + i); - uint16_t codepage_id = *reinterpret_cast<const uint16_t*>(resource_data.data() + value_pos + sizeof(uint16_t) + i); - //Save translation - translations.insert(std::make_pair(lang_id, codepage_id)); - } - } - - //Navigate to next var block - var_table_pos += pe_utils::align_up(var_table->Length, sizeof(uint32_t)); - } - } - else - { - throw_incorrect_version_info(); - } - - //Navigate to next element in root block - child_pos += pe_utils::align_up(block->Length, sizeof(uint32_t)); - } - - return ret; -} - -//Returns full version information: -//file_version info: versions and file info -//lang_string_values_map: map of version info strings with encodings -//translation_values_map: map of translations -const file_version_info resource_version_info_reader::get_version_info_by_lang(lang_string_values_map& string_values, translation_values_map& translations, uint32_t language) const -{ - const std::string& resource_data = res_.get_root_directory() //Type directory - .entry_by_id(pe_resource_viewer::resource_version) - .get_resource_directory() //Name/ID directory - .entry_by_id(1) - .get_resource_directory() //Language directory - .entry_by_id(language) - .get_data_entry() //Data directory - .get_data(); - - return get_version_info(string_values, translations, resource_data); -} - -//Returns full version information: -//file_version_info: versions and file info -//lang_string_values_map: map of version info strings with encodings -//translation_values_map: map of translations -const file_version_info resource_version_info_reader::get_version_info(lang_string_values_map& string_values, translation_values_map& translations, uint32_t index) const -{ - const resource_directory::entry_list& entries = res_.get_root_directory() //Type directory - .entry_by_id(pe_resource_viewer::resource_version) - .get_resource_directory() //Name/ID directory - .entry_by_id(1) - .get_resource_directory() //Language directory - .get_entry_list(); - - if(entries.size() <= index) - throw pe_exception("Resource data entry not found", pe_exception::resource_data_entry_not_found); - - return get_version_info(string_values, translations, entries.at(index).get_data_entry().get_data()); //Data directory -} -} diff --git a/tools/pe_bliss/resource_version_info_reader.h b/tools/pe_bliss/resource_version_info_reader.h deleted file mode 100644 index c1dfbffdc2..0000000000 --- a/tools/pe_bliss/resource_version_info_reader.h +++ /dev/null @@ -1,67 +0,0 @@ -/*************************************************************************/ -/* Copyright (c) 2015 dx, http://kaimi.ru */ -/* */ -/* Permission is hereby granted, free of charge, to any person */ -/* obtaining a copy of this software and associated documentation */ -/* files (the "Software"), to deal in the Software without */ -/* restriction, including without limitation the rights to use, */ -/* copy, modify, merge, publish, distribute, sublicense, and/or */ -/* sell copies of the Software, and to permit persons to whom the */ -/* Software is furnished to do so, subject to the following conditions: */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#pragma once -#include <map> -#include "file_version_info.h" -#include "pe_structures.h" -#include "version_info_types.h" - -namespace pe_bliss -{ -class pe_resource_viewer; - -class resource_version_info_reader -{ -public: //VERSION INFO - resource_version_info_reader(const pe_resource_viewer& res); - - //Returns full version information: - //file_version_info: versions and file info - //lang_lang_string_values_map: map of version info strings with encodings with encodings - //translation_values_map: map of translations - const file_version_info get_version_info(lang_string_values_map& string_values, translation_values_map& translations, uint32_t index = 0) const; - const file_version_info get_version_info_by_lang(lang_string_values_map& string_values, translation_values_map& translations, uint32_t language) const; - -public: - //L"VS_VERSION_INFO" key of root version info block - static const u16string version_info_key; - -private: - const pe_resource_viewer& res_; - - //VERSION INFO helpers - //Returns aligned version block value position - static uint32_t get_version_block_value_pos(uint32_t base_pos, const unicode16_t* key); - - //Returns aligned version block first child position - static uint32_t get_version_block_first_child_pos(uint32_t base_pos, uint32_t value_length, const unicode16_t* key); - - //Returns full version information: - //file_version_info: versions and file info - //lang_string_values_map: map of version info strings with encodings - //translation_values_map: map of translations - const file_version_info get_version_info(lang_string_values_map& string_values, translation_values_map& translations, const std::string& resource_data) const; - - //Throws an exception (id = resource_incorrect_version_info) - static void throw_incorrect_version_info(); -}; -} diff --git a/tools/pe_bliss/resource_version_info_writer.cpp b/tools/pe_bliss/resource_version_info_writer.cpp deleted file mode 100644 index ed95a0f7ea..0000000000 --- a/tools/pe_bliss/resource_version_info_writer.cpp +++ /dev/null @@ -1,283 +0,0 @@ -/*************************************************************************/ -/* Copyright (c) 2015 dx, http://kaimi.ru */ -/* */ -/* Permission is hereby granted, free of charge, to any person */ -/* obtaining a copy of this software and associated documentation */ -/* files (the "Software"), to deal in the Software without */ -/* restriction, including without limitation the rights to use, */ -/* copy, modify, merge, publish, distribute, sublicense, and/or */ -/* sell copies of the Software, and to permit persons to whom the */ -/* Software is furnished to do so, subject to the following conditions: */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#include <string.h> -#include "resource_version_info_writer.h" -#include "pe_structures.h" -#include "resource_internal.h" -#include "utils.h" -#include "pe_resource_manager.h" -#include "resource_version_info_reader.h" - -namespace pe_bliss -{ -using namespace pe_win; - -resource_version_info_writer::resource_version_info_writer(pe_resource_manager& res) - :res_(res) -{} - -//Sets/replaces full version information: -//file_version_info: versions and file info -//lang_string_values_map: map of version info strings with encodings -//translation_values_map: map of translations -void resource_version_info_writer::set_version_info(const file_version_info& file_info, - const lang_string_values_map& string_values, - const translation_values_map& translations, - uint32_t language, - uint32_t codepage, - uint32_t timestamp) -{ - std::string version_data; - - //Calculate total size of version resource data - uint32_t total_version_info_length = - static_cast<uint32_t>(sizeof(version_info_block) - sizeof(uint16_t) + sizeof(uint16_t) /* pading */ - + (resource_version_info_reader::version_info_key.length() + 1) * 2 - + sizeof(vs_fixedfileinfo)); - - //If we have any strings values - if(!string_values.empty()) - { - total_version_info_length += sizeof(version_info_block) - sizeof(uint16_t); //StringFileInfo block - total_version_info_length += SizeofStringFileInfo; //Name of block (key) - - //Add required size for version strings - for(lang_string_values_map::const_iterator table_it = string_values.begin(); table_it != string_values.end(); ++table_it) - { - total_version_info_length += pe_utils::align_up(static_cast<uint32_t>(sizeof(uint16_t) * 3 + ((*table_it).first.length() + 1) * 2), sizeof(uint32_t)); //Name of child block and block size (key of string table block) - - const string_values_map& values = (*table_it).second; - for(string_values_map::const_iterator it = values.begin(); it != values.end(); ++it) - { - total_version_info_length += pe_utils::align_up(static_cast<uint32_t>(sizeof(uint16_t) * 3 + ((*it).first.length() + 1) * 2), sizeof(uint32_t)); - total_version_info_length += pe_utils::align_up(static_cast<uint32_t>(((*it).second.length() + 1) * 2), sizeof(uint32_t)); - } - } - } - - //If we have translations - if(!translations.empty()) - { - total_version_info_length += (sizeof(version_info_block) - sizeof(uint16_t)) * 2; //VarFileInfo and Translation blocks - total_version_info_length += SizeofVarFileInfoAligned; //DWORD-aligned VarFileInfo block name - total_version_info_length += SizeofTranslationAligned; //DWORD-aligned Translation block name - total_version_info_length += static_cast<uint32_t>(translations.size() * sizeof(uint16_t) * 2); - } - - //Resize version data buffer - version_data.resize(total_version_info_length); - - //Create root version block - version_info_block root_block = {0}; - root_block.ValueLength = sizeof(vs_fixedfileinfo); - root_block.Length = static_cast<uint16_t>(total_version_info_length); - - //Fill fixed file info - vs_fixedfileinfo fixed_info = {0}; - fixed_info.dwFileDateLS = file_info.get_file_date_ls(); - fixed_info.dwFileDateMS = file_info.get_file_date_ms(); - fixed_info.dwFileFlags = file_info.get_file_flags(); - fixed_info.dwFileFlagsMask = vs_ffi_fileflagsmask; - fixed_info.dwFileOS = file_info.get_file_os_raw(); - fixed_info.dwFileSubtype = file_info.get_file_subtype(); - fixed_info.dwFileType = file_info.get_file_type_raw(); - fixed_info.dwFileVersionLS = file_info.get_file_version_ls(); - fixed_info.dwFileVersionMS = file_info.get_file_version_ms(); - fixed_info.dwSignature = vs_ffi_signature; - fixed_info.dwStrucVersion = vs_ffi_strucversion; - fixed_info.dwProductVersionLS = file_info.get_product_version_ls(); - fixed_info.dwProductVersionMS = file_info.get_product_version_ms(); - - //Write root block and fixed file info to buffer - uint32_t data_ptr = 0; - memcpy(&version_data[data_ptr], &root_block, sizeof(version_info_block) - sizeof(uint16_t)); - data_ptr += sizeof(version_info_block) - sizeof(uint16_t); - memcpy(&version_data[data_ptr], resource_version_info_reader::version_info_key.c_str(), (resource_version_info_reader::version_info_key.length() + 1) * sizeof(uint16_t)); - data_ptr += static_cast<uint32_t>((resource_version_info_reader::version_info_key.length() + 1) * sizeof(uint16_t)); - memset(&version_data[data_ptr], 0, sizeof(uint16_t)); - data_ptr += sizeof(uint16_t); - memcpy(&version_data[data_ptr], &fixed_info, sizeof(fixed_info)); - data_ptr += sizeof(fixed_info); - - //Write string values, if any - if(!string_values.empty()) - { - //Create string file info root block - version_info_block string_file_info_block = {0}; - string_file_info_block.Type = 1; //Block type is string - memcpy(&version_data[data_ptr], &string_file_info_block, sizeof(version_info_block) - sizeof(uint16_t)); - //We will calculate its length later - version_info_block* string_file_info_block_ptr = reinterpret_cast<version_info_block*>(&version_data[data_ptr]); - data_ptr += sizeof(version_info_block) - sizeof(uint16_t); - - uint32_t old_ptr1 = data_ptr; //Used to calculate string file info block length later - memcpy(&version_data[data_ptr], StringFileInfo, SizeofStringFileInfo); //Write block name - data_ptr += SizeofStringFileInfo; - - //Create string table root block (child of string file info) - version_info_block string_table_block = {0}; - string_table_block.Type = 1; //Block type is string - - for(lang_string_values_map::const_iterator table_it = string_values.begin(); table_it != string_values.end(); ++table_it) - { - const string_values_map& values = (*table_it).second; - - memcpy(&version_data[data_ptr], &string_table_block, sizeof(version_info_block) - sizeof(uint16_t)); - //We will calculate its length later - version_info_block* string_table_block_ptr = reinterpret_cast<version_info_block*>(&version_data[data_ptr]); - data_ptr += sizeof(version_info_block) - sizeof(uint16_t); - - uint32_t old_ptr2 = data_ptr; //Used to calculate string table block length later - uint32_t lang_key_length = static_cast<uint32_t>(((*table_it).first.length() + 1) * sizeof(uint16_t)); - -#ifdef PE_BLISS_WINDOWS - memcpy(&version_data[data_ptr], (*table_it).first.c_str(), lang_key_length); //Write block key -#else - { - u16string str(pe_utils::to_ucs2((*table_it).first)); - memcpy(&version_data[data_ptr], str.c_str(), lang_key_length); //Write block key - } -#endif - - data_ptr += lang_key_length; - //Align key if necessary - if((sizeof(uint16_t) * 3 + lang_key_length) % sizeof(uint32_t)) - { - memset(&version_data[data_ptr], 0, sizeof(uint16_t)); - data_ptr += sizeof(uint16_t); - } - - //Create string block (child of string table block) - version_info_block string_block = {0}; - string_block.Type = 1; //Block type is string - for(string_values_map::const_iterator it = values.begin(); it != values.end(); ++it) - { - //Calculate value length and key length of string block - string_block.ValueLength = static_cast<uint16_t>((*it).second.length() + 1); - uint32_t key_length = static_cast<uint32_t>(((*it).first.length() + 1) * sizeof(uint16_t)); - //Calculate length of block - string_block.Length = static_cast<uint16_t>(pe_utils::align_up(sizeof(uint16_t) * 3 + key_length, sizeof(uint32_t)) + string_block.ValueLength * sizeof(uint16_t)); - - //Write string block - memcpy(&version_data[data_ptr], &string_block, sizeof(version_info_block) - sizeof(uint16_t)); - data_ptr += sizeof(version_info_block) - sizeof(uint16_t); - -#ifdef PE_BLISS_WINDOWS - memcpy(&version_data[data_ptr], (*it).first.c_str(), key_length); //Write block key -#else - { - u16string str(pe_utils::to_ucs2((*it).first)); - memcpy(&version_data[data_ptr], str.c_str(), key_length); //Write block key - } -#endif - - data_ptr += key_length; - //Align key if necessary - if((sizeof(uint16_t) * 3 + key_length) % sizeof(uint32_t)) - { - memset(&version_data[data_ptr], 0, sizeof(uint16_t)); - data_ptr += sizeof(uint16_t); - } - - //Write block data (value) -#ifdef PE_BLISS_WINDOWS - memcpy(&version_data[data_ptr], (*it).second.c_str(), string_block.ValueLength * sizeof(uint16_t)); -#else - { - u16string str(pe_utils::to_ucs2((*it).second)); - memcpy(&version_data[data_ptr], str.c_str(), string_block.ValueLength * sizeof(uint16_t)); - } -#endif - - data_ptr += string_block.ValueLength * 2; - //Align data if necessary - if((string_block.ValueLength * 2) % sizeof(uint32_t)) - { - memset(&version_data[data_ptr], 0, sizeof(uint16_t)); - data_ptr += sizeof(uint16_t); - } - } - - //Calculate string table and string file info blocks lengths - string_table_block_ptr->Length = static_cast<uint16_t>(data_ptr - old_ptr2 + sizeof(uint16_t) * 3); - } - - string_file_info_block_ptr->Length = static_cast<uint16_t>(data_ptr - old_ptr1 + sizeof(uint16_t) * 3); - } - - //If we have transactions - if(!translations.empty()) - { - //Create root var file info block - version_info_block var_file_info_block = {0}; - var_file_info_block.Type = 1; //Type of block is string - //Write block header - memcpy(&version_data[data_ptr], &var_file_info_block, sizeof(version_info_block) - sizeof(uint16_t)); - //We will calculate its length later - version_info_block* var_file_info_block_ptr = reinterpret_cast<version_info_block*>(&version_data[data_ptr]); - data_ptr += sizeof(version_info_block) - sizeof(uint16_t); - - uint32_t old_ptr1 = data_ptr; //Used to calculate var file info block length later - memcpy(&version_data[data_ptr], VarFileInfoAligned, SizeofVarFileInfoAligned); //Write block key (aligned) - data_ptr += SizeofVarFileInfoAligned; - - //Create root translation block (child of var file info block) - version_info_block translation_block = {0}; - //Write block header - memcpy(&version_data[data_ptr], &translation_block, sizeof(version_info_block) - sizeof(uint16_t)); - //We will calculate its length later - version_info_block* translation_block_ptr = reinterpret_cast<version_info_block*>(&version_data[data_ptr]); - data_ptr += sizeof(version_info_block) - sizeof(uint16_t); - - uint32_t old_ptr2 = data_ptr; //Used to calculate var file info block length later - memcpy(&version_data[data_ptr], TranslationAligned, SizeofTranslationAligned); //Write block key (aligned) - data_ptr += SizeofTranslationAligned; - - //Calculate translation block value length - translation_block_ptr->ValueLength = static_cast<uint16_t>(sizeof(uint16_t) * 2 * translations.size()); - - //Write translation values to block - for(translation_values_map::const_iterator it = translations.begin(); it != translations.end(); ++it) - { - uint16_t lang_id = (*it).first; //Language ID - uint16_t codepage_id = (*it).second; //Codepage ID - memcpy(&version_data[data_ptr], &lang_id, sizeof(lang_id)); - data_ptr += sizeof(lang_id); - memcpy(&version_data[data_ptr], &codepage_id, sizeof(codepage_id)); - data_ptr += sizeof(codepage_id); - } - - //Calculate Translation and VarFileInfo blocks lengths - translation_block_ptr->Length = static_cast<uint16_t>(data_ptr - old_ptr2 + sizeof(uint16_t) * 3); - var_file_info_block_ptr->Length = static_cast<uint16_t>(data_ptr - old_ptr1 + sizeof(uint16_t) * 3); - } - - //Add/replace version info resource - res_.add_resource(version_data, pe_resource_viewer::resource_version, 1, language, codepage, timestamp); -} - -//Removes version info by language (ID = 1) -bool resource_version_info_writer::remove_version_info(uint32_t language) -{ - return res_.remove_resource(pe_resource_viewer::resource_version, 1, language); -} -} diff --git a/tools/pe_bliss/resource_version_info_writer.h b/tools/pe_bliss/resource_version_info_writer.h deleted file mode 100644 index da279ddedb..0000000000 --- a/tools/pe_bliss/resource_version_info_writer.h +++ /dev/null @@ -1,52 +0,0 @@ -/*************************************************************************/ -/* Copyright (c) 2015 dx, http://kaimi.ru */ -/* */ -/* Permission is hereby granted, free of charge, to any person */ -/* obtaining a copy of this software and associated documentation */ -/* files (the "Software"), to deal in the Software without */ -/* restriction, including without limitation the rights to use, */ -/* copy, modify, merge, publish, distribute, sublicense, and/or */ -/* sell copies of the Software, and to permit persons to whom the */ -/* Software is furnished to do so, subject to the following conditions: */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#pragma once -#include "version_info_types.h" -#include "file_version_info.h" - -namespace pe_bliss -{ -class pe_resource_manager; - -class resource_version_info_writer -{ -public: - resource_version_info_writer(pe_resource_manager& res); - - //Sets/replaces full version information: - //file_version_info: versions and file info - //lang_string_values_map: map of version info strings with encodings - //translation_values_map: map of translations - void set_version_info(const file_version_info& file_info, - const lang_string_values_map& string_values, - const translation_values_map& translations, - uint32_t language, - uint32_t codepage = 0, - uint32_t timestamp = 0); - - //Removes version info by language (ID = 1) - bool remove_version_info(uint32_t language); - -private: - pe_resource_manager& res_; -}; -} diff --git a/tools/pe_bliss/stdint_defs.h b/tools/pe_bliss/stdint_defs.h deleted file mode 100644 index bbc003690a..0000000000 --- a/tools/pe_bliss/stdint_defs.h +++ /dev/null @@ -1,45 +0,0 @@ -/*************************************************************************/ -/* Copyright (c) 2015 dx, http://kaimi.ru */ -/* */ -/* Permission is hereby granted, free of charge, to any person */ -/* obtaining a copy of this software and associated documentation */ -/* files (the "Software"), to deal in the Software without */ -/* restriction, including without limitation the rights to use, */ -/* copy, modify, merge, publish, distribute, sublicense, and/or */ -/* sell copies of the Software, and to permit persons to whom the */ -/* Software is furnished to do so, subject to the following conditions: */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#pragma once -#ifdef _MSC_VER -#if _MSC_VER < 1600 -namespace pe_bliss -{ - //stdint.h definitions for MSVC 2008 and earlier, as - //it doesn't have them - typedef signed char int8_t; - typedef short int16_t; - typedef int int32_t; - - typedef unsigned char uint8_t; - typedef unsigned short uint16_t; - typedef unsigned int uint32_t; - - typedef long long int64_t; - typedef unsigned long long uint64_t; -} -#else -#include <stdint.h> -#endif -#else -#include <stdint.h> -#endif diff --git a/tools/pe_bliss/utils.cpp b/tools/pe_bliss/utils.cpp deleted file mode 100644 index e6a75d5497..0000000000 --- a/tools/pe_bliss/utils.cpp +++ /dev/null @@ -1,85 +0,0 @@ -/*************************************************************************/ -/* Copyright (c) 2015 dx, http://kaimi.ru */ -/* */ -/* Permission is hereby granted, free of charge, to any person */ -/* obtaining a copy of this software and associated documentation */ -/* files (the "Software"), to deal in the Software without */ -/* restriction, including without limitation the rights to use, */ -/* copy, modify, merge, publish, distribute, sublicense, and/or */ -/* sell copies of the Software, and to permit persons to whom the */ -/* Software is furnished to do so, subject to the following conditions: */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#include <string.h> -#include "utils.h" -#include "pe_exception.h" - - -namespace pe_bliss -{ -const double pe_utils::log_2 = 1.44269504088896340736; //instead of using M_LOG2E - -//Returns stream size -std::streamoff pe_utils::get_file_size(std::istream& file) -{ - //Get old istream offset - std::streamoff old_offset = file.tellg(); - file.seekg(0, std::ios::end); - std::streamoff filesize = file.tellg(); - //Set old istream offset - file.seekg(old_offset); - return filesize; -} - -#ifndef PE_BLISS_WINDOWS -const u16string pe_utils::to_ucs2(const std::wstring& str) -{ - u16string ret; - if(str.empty()) - return ret; - - int len = str.length(); - - ret.resize(len); - - for(int i=0;i<len;i++) { - ret[i]=str[i]&0xFFFF; - } - - return ret; -} - -const std::wstring pe_utils::from_ucs2(const u16string& str) -{ - std::wstring ret; - if(str.empty()) - return ret; - - int len = str.length(); - ret.resize(str.length()); - - for(int i=0;i<len;i++) { - ret[i]=str[i]; - } - - return ret; -} -#endif - -bool operator==(const pe_win::guid& guid1, const pe_win::guid& guid2) -{ - return guid1.Data1 == guid2.Data1 - && guid1.Data2 == guid2.Data2 - && guid1.Data3 == guid2.Data3 - && !memcmp(guid1.Data4, guid2.Data4, sizeof(guid1.Data4)); -} -} diff --git a/tools/pe_bliss/utils.h b/tools/pe_bliss/utils.h deleted file mode 100644 index 29125f8dc1..0000000000 --- a/tools/pe_bliss/utils.h +++ /dev/null @@ -1,105 +0,0 @@ -/*************************************************************************/ -/* Copyright (c) 2015 dx, http://kaimi.ru */ -/* */ -/* Permission is hereby granted, free of charge, to any person */ -/* obtaining a copy of this software and associated documentation */ -/* files (the "Software"), to deal in the Software without */ -/* restriction, including without limitation the rights to use, */ -/* copy, modify, merge, publish, distribute, sublicense, and/or */ -/* sell copies of the Software, and to permit persons to whom the */ -/* Software is furnished to do so, subject to the following conditions: */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#pragma once -#include <istream> -#include <string> -#include "stdint_defs.h" -#include "pe_structures.h" - -namespace pe_bliss -{ -class pe_utils -{ -public: - //Returns true if string "data" with maximum length "raw_length" is null-terminated - template<typename T> - static bool is_null_terminated(const T* data, size_t raw_length) - { - raw_length /= sizeof(T); - for(size_t l = 0; l < raw_length; l++) - { - if(data[l] == static_cast<T>(L'\0')) - return true; - } - - return false; - } - - //Helper template function to strip nullbytes in the end of string - template<typename T> - static void strip_nullbytes(std::basic_string<T>& str) - { - while(!*(str.end() - 1) && !str.empty()) - str.erase(str.length() - 1); - } - - //Helper function to determine if number is power of 2 - template<typename T> - static inline bool is_power_of_2(T x) - { - return !(x & (x - 1)); - } - - //Helper function to align number down - template<typename T> - static inline T align_down(T x, uint32_t align) - { - return x & ~(static_cast<T>(align) - 1); - } - - //Helper function to align number up - template<typename T> - static inline T align_up(T x, uint32_t align) - { - return (x & static_cast<T>(align - 1)) ? align_down(x, align) + static_cast<T>(align) : x; - } - - //Returns true if sum of two unsigned integers is safe (no overflow occurs) - static inline bool is_sum_safe(uint32_t a, uint32_t b) - { - return a <= static_cast<uint32_t>(-1) - b; - } - - //Two gigabytes value in bytes - static const uint32_t two_gb = 0x80000000; - static const uint32_t max_dword = 0xFFFFFFFF; - static const uint32_t max_word = 0x0000FFFF; - static const double log_2; //instead of using M_LOG2E - - //Returns stream size - static std::streamoff get_file_size(std::istream& file); - -#ifndef PE_BLISS_WINDOWS -public: - static const u16string to_ucs2(const std::wstring& str); - static const std::wstring from_ucs2(const u16string& str); -#endif - -private: - pe_utils(); - pe_utils(pe_utils&); - pe_utils& operator=(const pe_utils&); -}; - -//Windows GUID comparison -bool operator==(const pe_win::guid& guid1, const pe_win::guid& guid2); -} diff --git a/tools/pe_bliss/version_info_editor.cpp b/tools/pe_bliss/version_info_editor.cpp deleted file mode 100644 index 199eebfd54..0000000000 --- a/tools/pe_bliss/version_info_editor.cpp +++ /dev/null @@ -1,184 +0,0 @@ -/*************************************************************************/ -/* Copyright (c) 2015 dx, http://kaimi.ru */ -/* */ -/* Permission is hereby granted, free of charge, to any person */ -/* obtaining a copy of this software and associated documentation */ -/* files (the "Software"), to deal in the Software without */ -/* restriction, including without limitation the rights to use, */ -/* copy, modify, merge, publish, distribute, sublicense, and/or */ -/* sell copies of the Software, and to permit persons to whom the */ -/* Software is furnished to do so, subject to the following conditions: */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#include <sstream> -#include <iomanip> -#include "version_info_types.h" -#include "version_info_editor.h" -#include "version_info_viewer.h" - -namespace pe_bliss -{ -//Default constructor -//strings - version info strings with charsets -//translations - version info translations map -version_info_editor::version_info_editor(lang_string_values_map& strings, translation_values_map& translations) - :version_info_viewer(strings, translations), - strings_edit_(strings), - translations_edit_(translations) -{} - -//Below functions have parameter translation -//If it's empty, the default language translation will be taken -//If there's no default language translation, the first one will be taken - -//Sets company name -void version_info_editor::set_company_name(const std::wstring& value, const std::wstring& translation) -{ - set_property(L"CompanyName", value, translation); -} - -//Sets file description -void version_info_editor::set_file_description(const std::wstring& value, const std::wstring& translation) -{ - set_property(L"FileDescription", value, translation); -} - -//Sets file version -void version_info_editor::set_file_version(const std::wstring& value, const std::wstring& translation) -{ - set_property(L"FileVersion", value, translation); -} - -//Sets internal file name -void version_info_editor::set_internal_name(const std::wstring& value, const std::wstring& translation) -{ - set_property(L"InternalName", value, translation); -} - -//Sets legal copyright -void version_info_editor::set_legal_copyright(const std::wstring& value, const std::wstring& translation) -{ - set_property(L"LegalCopyright", value, translation); -} - -//Sets original file name -void version_info_editor::set_original_filename(const std::wstring& value, const std::wstring& translation) -{ - set_property(L"OriginalFilename", value, translation); -} - -//Sets product name -void version_info_editor::set_product_name(const std::wstring& value, const std::wstring& translation) -{ - set_property(L"ProductName", value, translation); -} - -//Sets product version -void version_info_editor::set_product_version(const std::wstring& value, const std::wstring& translation) -{ - set_property(L"ProductVersion", value, translation); -} - -//Sets version info property value -//property_name - property name -//value - property value -//If translation does not exist, it will be added -//If property does not exist, it will be added -void version_info_editor::set_property(const std::wstring& property_name, const std::wstring& value, const std::wstring& translation) -{ - lang_string_values_map::iterator it = strings_edit_.begin(); - - if(translation.empty()) - { - //If no translation was specified - it = strings_edit_.find(default_language_translation); //Find default translation table - if(it == strings_edit_.end()) //If there's no default translation table, take the first one - { - it = strings_edit_.begin(); - if(it == strings_edit_.end()) //If there's no any translation table, add default one - { - it = strings_edit_.insert(std::make_pair(default_language_translation, string_values_map())).first; - //Also add it to translations list - add_translation(default_language_translation); - } - } - } - else - { - it = strings_edit_.find(translation); //Find specified translation table - if(it == strings_edit_.end()) //If there's no translation, add it - { - it = strings_edit_.insert(std::make_pair(translation, string_values_map())).first; - //Also add it to translations list - add_translation(translation); - } - } - - //Change value of the required property - ((*it).second)[property_name] = value; -} - -//Adds translation to translation list -void version_info_editor::add_translation(const std::wstring& translation) -{ - std::pair<uint16_t, uint16_t> translation_ids(translation_from_string(translation)); - add_translation(translation_ids.first, translation_ids.second); -} - -void version_info_editor::add_translation(uint16_t language_id, uint16_t codepage_id) -{ - std::pair<translation_values_map::const_iterator, translation_values_map::const_iterator> - range(translations_edit_.equal_range(language_id)); - - //If translation already exists - for(translation_values_map::const_iterator it = range.first; it != range.second; ++it) - { - if((*it).second == codepage_id) - return; - } - - translations_edit_.insert(std::make_pair(language_id, codepage_id)); -} - -//Removes translation from translations and strings lists -void version_info_editor::remove_translation(const std::wstring& translation) -{ - std::pair<uint16_t, uint16_t> translation_ids(translation_from_string(translation)); - remove_translation(translation_ids.first, translation_ids.second); -} - -void version_info_editor::remove_translation(uint16_t language_id, uint16_t codepage_id) -{ - { - //Erase string table (if exists) - std::wstringstream ss; - ss << std::hex - << std::setw(4) << std::setfill(L'0') << language_id - << std::setw(4) << std::setfill(L'0') << codepage_id; - - strings_edit_.erase(ss.str()); - } - - //Find and erase translation from translations table - std::pair<translation_values_map::iterator, translation_values_map::iterator> - it_pair = translations_edit_.equal_range(language_id); - - for(translation_values_map::iterator it = it_pair.first; it != it_pair.second; ++it) - { - if((*it).second == codepage_id) - { - translations_edit_.erase(it); - break; - } - } -} -} diff --git a/tools/pe_bliss/version_info_editor.h b/tools/pe_bliss/version_info_editor.h deleted file mode 100644 index 53d3dc62c1..0000000000 --- a/tools/pe_bliss/version_info_editor.h +++ /dev/null @@ -1,79 +0,0 @@ -/*************************************************************************/ -/* Copyright (c) 2015 dx, http://kaimi.ru */ -/* */ -/* Permission is hereby granted, free of charge, to any person */ -/* obtaining a copy of this software and associated documentation */ -/* files (the "Software"), to deal in the Software without */ -/* restriction, including without limitation the rights to use, */ -/* copy, modify, merge, publish, distribute, sublicense, and/or */ -/* sell copies of the Software, and to permit persons to whom the */ -/* Software is furnished to do so, subject to the following conditions: */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#pragma once -#include "version_info_types.h" -#include "version_info_viewer.h" - -namespace pe_bliss -{ - //Helper class to read and edit version information - //lang_string_values_map: map of version info strings with encodings - //translation_values_map: map of translations - class version_info_editor : public version_info_viewer - { - public: - //Default constructor - //strings - version info strings with charsets - //translations - version info translations map - version_info_editor(lang_string_values_map& strings, translation_values_map& translations); - - //Below functions have parameter translation - //If it's empty, the default language translation will be taken - //If there's no default language translation, the first one will be taken - - //Sets company name - void set_company_name(const std::wstring& value, const std::wstring& translation = std::wstring()); - //Sets file description - void set_file_description(const std::wstring& value, const std::wstring& translation = std::wstring()); - //Sets file version - void set_file_version(const std::wstring& value, const std::wstring& translation = std::wstring()); - //Sets internal file name - void set_internal_name(const std::wstring& value, const std::wstring& translation = std::wstring()); - //Sets legal copyright - void set_legal_copyright(const std::wstring& value, const std::wstring& translation = std::wstring()); - //Sets original file name - void set_original_filename(const std::wstring& value, const std::wstring& translation = std::wstring()); - //Sets product name - void set_product_name(const std::wstring& value, const std::wstring& translation = std::wstring()); - //Sets product version - void set_product_version(const std::wstring& value, const std::wstring& translation = std::wstring()); - - //Sets version info property value - //property_name - property name - //value - property value - //If translation does not exist, it will be added to strings and translations lists - //If property does not exist, it will be added - void set_property(const std::wstring& property_name, const std::wstring& value, const std::wstring& translation = std::wstring()); - - //Adds translation to translation list - void add_translation(const std::wstring& translation); - void add_translation(uint16_t language_id, uint16_t codepage_id); - - //Removes translation from translations and strings lists - void remove_translation(const std::wstring& translation); - void remove_translation(uint16_t language_id, uint16_t codepage_id); - - private: - lang_string_values_map& strings_edit_; - translation_values_map& translations_edit_; - }; -} diff --git a/tools/pe_bliss/version_info_types.h b/tools/pe_bliss/version_info_types.h deleted file mode 100644 index 6010c9691e..0000000000 --- a/tools/pe_bliss/version_info_types.h +++ /dev/null @@ -1,38 +0,0 @@ -/*************************************************************************/ -/* Copyright (c) 2015 dx, http://kaimi.ru */ -/* */ -/* Permission is hereby granted, free of charge, to any person */ -/* obtaining a copy of this software and associated documentation */ -/* files (the "Software"), to deal in the Software without */ -/* restriction, including without limitation the rights to use, */ -/* copy, modify, merge, publish, distribute, sublicense, and/or */ -/* sell copies of the Software, and to permit persons to whom the */ -/* Software is furnished to do so, subject to the following conditions: */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#pragma once -#include <map> -#include <string> -#include "stdint_defs.h" - -namespace pe_bliss -{ - //Typedef for version info functions: Name - Value - typedef std::map<std::wstring, std::wstring> string_values_map; - //Typedef for version info functions: Language string - String Values Map - //Language String consists of LangID and CharsetID - //E.g. 041904b0 for Russian UNICODE, 040004b0 for Process Default Language UNICODE - typedef std::map<std::wstring, string_values_map> lang_string_values_map; - - //Typedef for version info functions: Language - Character Set - typedef std::multimap<uint16_t, uint16_t> translation_values_map; -} diff --git a/tools/pe_bliss/version_info_viewer.cpp b/tools/pe_bliss/version_info_viewer.cpp deleted file mode 100644 index 6e2d0d5c5b..0000000000 --- a/tools/pe_bliss/version_info_viewer.cpp +++ /dev/null @@ -1,180 +0,0 @@ -/*************************************************************************/ -/* Copyright (c) 2015 dx, http://kaimi.ru */ -/* */ -/* Permission is hereby granted, free of charge, to any person */ -/* obtaining a copy of this software and associated documentation */ -/* files (the "Software"), to deal in the Software without */ -/* restriction, including without limitation the rights to use, */ -/* copy, modify, merge, publish, distribute, sublicense, and/or */ -/* sell copies of the Software, and to permit persons to whom the */ -/* Software is furnished to do so, subject to the following conditions: */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#include <iomanip> -#include <sstream> -#include "pe_exception.h" -#include "version_info_viewer.h" - -namespace pe_bliss -{ -//Default process language, UNICODE -const std::wstring version_info_viewer::default_language_translation(L"040904b0"); - -//Default constructor -//strings - version info strings with charsets -//translations - version info translations map -version_info_viewer::version_info_viewer(const lang_string_values_map& strings, const translation_values_map& translations) - :strings_(strings), translations_(translations) -{} - -//Below functions have parameter translation -//If it's empty, the default language translation will be taken -//If there's no default language translation, the first one will be taken - -//Returns company name -const std::wstring version_info_viewer::get_company_name(const std::wstring& translation) const -{ - return get_property(L"CompanyName", translation); -} - -//Returns file description -const std::wstring version_info_viewer::get_file_description(const std::wstring& translation) const -{ - return get_property(L"FileDescription", translation); -} - -//Returns file version -const std::wstring version_info_viewer::get_file_version(const std::wstring& translation) const -{ - return get_property(L"FileVersion", translation); -} - -//Returns internal file name -const std::wstring version_info_viewer::get_internal_name(const std::wstring& translation) const -{ - return get_property(L"InternalName", translation); -} - -//Returns legal copyright -const std::wstring version_info_viewer::get_legal_copyright(const std::wstring& translation) const -{ - return get_property(L"LegalCopyright", translation); -} - -//Returns original file name -const std::wstring version_info_viewer::get_original_filename(const std::wstring& translation) const -{ - return get_property(L"OriginalFilename", translation); -} - -//Returns product name -const std::wstring version_info_viewer::get_product_name(const std::wstring& translation) const -{ - return get_property(L"ProductName", translation); -} - -//Returns product version -const std::wstring version_info_viewer::get_product_version(const std::wstring& translation) const -{ - return get_property(L"ProductVersion", translation); -} - -//Returns list of translations in string representation -const version_info_viewer::translation_list version_info_viewer::get_translation_list() const -{ - translation_list ret; - - //Enumerate all translations - for(translation_values_map::const_iterator it = translations_.begin(); it != translations_.end(); ++it) - { - //Create string representation of translation value - std::wstringstream ss; - ss << std::hex - << std::setw(4) << std::setfill(L'0') << (*it).first - << std::setw(4) << std::setfill(L'0') << (*it).second; - - //Save it - ret.push_back(ss.str()); - } - - return ret; -} - -//Returns version info property value -//property_name - required property name -//If throw_if_absent = true, will throw exception if property does not exist -//If throw_if_absent = false, will return empty string if property does not exist -const std::wstring version_info_viewer::get_property(const std::wstring& property_name, const std::wstring& translation, bool throw_if_absent) const -{ - std::wstring ret; - - //If there're no strings - if(strings_.empty()) - { - if(throw_if_absent) - throw pe_exception("Version info string does not exist", pe_exception::version_info_string_does_not_exist); - - return ret; - } - - lang_string_values_map::const_iterator it = strings_.begin(); - - if(translation.empty()) - { - //If no translation was specified - it = strings_.find(default_language_translation); //Find default translation table - if(it == strings_.end()) //If there's no default translation table, take the first one - it = strings_.begin(); - } - else - { - it = strings_.find(translation); //Find specified translation table - if(it == strings_.end()) - { - if(throw_if_absent) - throw pe_exception("Version info string does not exist", pe_exception::version_info_string_does_not_exist); - - return ret; - } - } - - //Find value of the required property - string_values_map::const_iterator str_it = (*it).second.find(property_name); - - if(str_it == (*it).second.end()) - { - if(throw_if_absent) - throw pe_exception("Version info string does not exist", pe_exception::version_info_string_does_not_exist); - - return ret; - } - - ret = (*str_it).second; - - return ret; -} - -//Converts translation HEX-string to pair of language ID and codepage ID -const version_info_viewer::translation_pair version_info_viewer::translation_from_string(const std::wstring& translation) -{ - uint32_t translation_id = 0; - - { - //Convert string to DWORD - std::wstringstream ss; - ss << std::hex << translation; - ss >> translation_id; - } - - return std::make_pair(static_cast<uint16_t>(translation_id >> 16), static_cast<uint16_t>(translation_id & 0xFFFF)); -} -} diff --git a/tools/pe_bliss/version_info_viewer.h b/tools/pe_bliss/version_info_viewer.h deleted file mode 100644 index bc2f6f2ba7..0000000000 --- a/tools/pe_bliss/version_info_viewer.h +++ /dev/null @@ -1,89 +0,0 @@ -/*************************************************************************/ -/* Copyright (c) 2015 dx, http://kaimi.ru */ -/* */ -/* Permission is hereby granted, free of charge, to any person */ -/* obtaining a copy of this software and associated documentation */ -/* files (the "Software"), to deal in the Software without */ -/* restriction, including without limitation the rights to use, */ -/* copy, modify, merge, publish, distribute, sublicense, and/or */ -/* sell copies of the Software, and to permit persons to whom the */ -/* Software is furnished to do so, subject to the following conditions: */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#pragma once -#include <map> -#include <vector> -#include <string> -#include "pe_resource_viewer.h" -#include "pe_structures.h" -#include "version_info_types.h" - -namespace pe_bliss -{ -//Helper class to read version information -//lang_string_values_map: map of version info strings with encodings -//translation_values_map: map of translations -class version_info_viewer -{ -public: - //Useful typedefs - typedef std::pair<uint16_t, uint16_t> translation_pair; - typedef std::vector<std::wstring> translation_list; - -public: - //Default constructor - //strings - version info strings with charsets - //translations - version info translations map - version_info_viewer(const lang_string_values_map& strings, const translation_values_map& translations); - - //Below functions have parameter translation - //If it's empty, the default language translation will be taken - //If there's no default language translation, the first one will be taken - - //Returns company name - const std::wstring get_company_name(const std::wstring& translation = std::wstring()) const; - //Returns file description - const std::wstring get_file_description(const std::wstring& translation = std::wstring()) const; - //Returns file version - const std::wstring get_file_version(const std::wstring& translation = std::wstring()) const; - //Returns internal file name - const std::wstring get_internal_name(const std::wstring& translation = std::wstring()) const; - //Returns legal copyright - const std::wstring get_legal_copyright(const std::wstring& translation = std::wstring()) const; - //Returns original file name - const std::wstring get_original_filename(const std::wstring& translation = std::wstring()) const; - //Returns product name - const std::wstring get_product_name(const std::wstring& translation = std::wstring()) const; - //Returns product version - const std::wstring get_product_version(const std::wstring& translation = std::wstring()) const; - - //Returns list of translations in string representation - const translation_list get_translation_list() const; - - //Returns version info property value - //property_name - required property name - //If throw_if_absent = true, will throw exception if property does not exist - //If throw_if_absent = false, will return empty string if property does not exist - const std::wstring get_property(const std::wstring& property_name, const std::wstring& translation = std::wstring(), bool throw_if_absent = false) const; - - //Converts translation HEX-string to pair of language ID and codepage ID - static const translation_pair translation_from_string(const std::wstring& translation); - -public: - //Default process language, UNICODE - static const std::wstring default_language_translation; - -private: - const lang_string_values_map& strings_; - const translation_values_map& translations_; -}; -} |