carchive源代码(carve中文)
admin 发布:2022-12-20 00:05 197
本篇文章给大家谈谈carchive源代码,以及carve中文对应的知识点,希望对各位有所帮助,不要忘了收藏本站喔。
本文目录一览:
- 1、用什么软件来查看一个用Microsoft Visual C++ 6.0 编写的程序的源代码
- 2、用 CArchive 写入数据出错
- 3、vc/mfc-如下一段CArchive的代码出现了“没有找到未命名文件”的错误(Release,运行时出错)
- 4、如何在c++中读取txt文件(最好有程序示例源代码)
- 5、如何使用CArchive类把一个树结构序列化到外存呢
用什么软件来查看一个用Microsoft Visual C++ 6.0 编写的程序的源代码
标 题: MFC逆向初级研究(1)
作 者: 北斗之摇光
时 间: 2007-03-15 17:14
链 接:
详细信息:
【文章标题】: MFC逆向初级研究(1)
【文章作者】: 北斗之摇光
【作者邮箱】: hardlywhen@hotmail.com
【下载地址】: 自己搜索下载
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
引言
本文主要针对微软的VC++6.0中使用MFC产生的EXE文件的逆向研究,我曾经使用微软的Visual Studio 2005编译了一
个EXE文件,通过IDA反汇编以后发现该文件与VC++6.0产生的文件还是有所区别,因此特别在此声明一下。文中主要使用了I
DA pro 5.0和在看雪()下载的OllyICE作为工具对目标文件进行反汇编。在此也感谢看雪论坛的各位的无私奉
献,在研究过程的中的困难多通过各位的帖子得到了帮助。
逆向的关键
我认为逆向的关键主要是要弄明白目标文件的算法和实现过程,在Window操作系统下,软件的实现过程就体现在其
对Window消息的处理,而软件的算法则包含在处理的具体过程中。对于通过SDK编写的"传统"的Windows应用程序基本都具备
几个共同的特征:WinMain函数、WinProc函数、窗口注册、消息循环。对于这类目标文件的分析主要集中的WinProc的分析上
,WinProc的函数地址获得一般是通过窗口注册函数中的参数获得。(由于我对于这类文件没有具体逆向过,所以只是大概的
说说,有不对的地方请各位不要客气,尽管拍砖)
而使用MFC(Microsoft Function Class)顾名思义,该类库主要封装了大部分的Windows API函数所以在代码中看
不到原本的SDK编程中的消息循环、窗口过程函数等等东西,所有这些封装在相应的mfcxx.dll中,让程序员能够专著与处理
过程与算法。这种做法于逆向而言有好处也有坏处:
坏处就是加大了对于MFC产生的EXE文件的逆向难度,让许多的和我一样的菜鸟迷失在汇编代码中找不找北了,基本主要就靠
猜测实现过程中用到了那些函数,然后对文件导入表的函数下断点来寻找我们所需要的处理过程;
好处就是这样的做法使得EXE文件中主要都是目标程序的Window消息处理流程以及算法,而且dll中的大部分函数的功能都能
在MSDN中查到。如果能够通过对目标文件的分析得到这个Window消息处理流程和算法架构,基本上我们就可以重写整个软件;
要做到上面的目标,首先我们要对MFC有所了解,推荐没有基础的兄弟们读读候俊杰的《深入浅出MFC》。该书在逆向过
程中完全可以作为一本参考书,让你能通过源代码了解实现过程,网上有很多该书的电子版下载。
一个逆向MFC产生的EXE文件的例子
下面我们就通过一个具体的例子来学习一下如何从目标文件中挖到我们需要的东西。首先我们来产生一个需要的EXE文件。
在此我假定各位对MFC有过一定的使用经验,毕竟逆向分析才是本文的重点。
1.产生例子所需要的目标文件:
我们通过VC++6.0的向导来产生一个名为ReverseMFC的工程,这个工程的设置情况如下:
Application type of fff:
Dialog-Based Application targeting:
Win32
Classes to be created:
Application: CFffApp in ReverseMFC.h and ReverseMFC.cpp
Dialog: CFffDlg in ReverseMFCDlg.h and ReverseMFCDlg.cpp
Features:
+ Uses shared DLL implementation (MFC42.DLL)
+ Localizable text in:
中文[中国]
直接编译以后就能够运行,为了确定我们是否正确的分析的整个目标文件,在该对话框中加入一个我们自定义的按钮如
下,对于该按钮的处理函数如下设定为:
AfxMessageBox("I find it!",MB_OK);编译后就得到了我们需要的目标文件。
现在我们得到了所需要的目标文件,在IDA中载入该文件。在此我们最好是产生Release版本的EXE文件,毕竟所有的发
布软件都是Release版本的。
2.具体分析
在IDA中按Ctrl+S找到.rdata段,该段主要存储了目标文件的类运行时创建信息、MessageMap信息、MessageEntry信息、
虚函数表、RTTI数据(如果编译选项中选择了支持RTTI的话)。
在到达.rdata段后我们可以看到这样的代码,对数据进行格式转换后可以得到如下图所示的数据。
.rdata:004021C0 ; 屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯?
.rdata:004021C0
.rdata:004021C0 ; Segment type: Pure data
.rdata:004021C0 ; Segment permissions: Read
.rdata:004021C0 _rdata segment para public 'DATA' use32
.rdata:004021C0 assume cs:_rdata
.rdata:004021C0 ;org 4021C0h
.rdata:004021C0 off_4021C0 dd offset sub_401000 ; DATA XREF: sub_401010o
.rdata:004021C4 dd offset dword_4021C8
.rdata:004021C8 dword_4021C8 dd 111h ; DATA XREF: .rdata:004021C4o
.rdata:004021CC dd 0
.rdata:004021D0 dd 0E146h
.rdata:004021D4 dd 0E146h
.rdata:004021D8 dd 0Ch
.rdata:004021DC dd offset CWinApp::OnHelp(void)
.rdata:004021E0 dd 0
.rdata:004021E4 dd 0
.rdata:004021E8 dd 0
.rdata:004021EC dd 0
.rdata:004021F0 dd 0
.rdata:004021F4 dd 0
.rdata:004021F8 off_4021F8 dd offset CWinApp::GetRuntimeClass(void)
.rdata:004021F8 ; DATA XREF: unknown_libname_1-56o
.rdata:004021FC dd offset sub_401040
.rdata:00402200 dd offset nullsub_2
.rdata:00402204 dd offset nullsub_3
.rdata:00402208 dd offset nullsub_2
.rdata:0040220C dd offset CCmdTarget::OnCmdMsg(uint,int,void *,AFX_CMDHANDLERINFO *)
其中的off_4021C0就是一个MessageMap数据;dword_4021C8就是MessageMap所指的MessageEntry数据;off_4021F8就是一个
类的虚函数表的开始位置。那么具体这些数据时那个类的相关数据呢?如此判断的依据是什么?
首先我们知道MessageEntry是的数据结构定义如下,而且以6个0表示整个数组的结束。
struct AFX_MSGMAP_ENTRY
{
UINT nMessage; // windows message
UINT nCode; // control code or WM_NOTIFY code
UINT nID; // control ID (or 0 for windows messages)
UINT nLastID; // used for entries specifying a range of control id's
UINT nSig; // signature type (action) or pointer to message #
AFX_PMSG pfn; // routine to call (or special value)
};
因此我们有理由假设"dword_4021C8就是MessageMap所指的MessageEntry数据"。
而MessageMap数据结构定义如下:
struct AFX_MSGMAP
{
#ifdef _AFXDLL
const AFX_MSGMAP* (PASCAL* pfnGetBaseMap)();
#else
const AFX_MSGMAP* pBaseMap;
#endif
const AFX_MSGMAP_ENTRY* lpEntries;
};
off_4021C0的两个数据中第二个数据恰恰就是我们前面假设为MessageEntry的指针,跟入其第一个数据,我们看到如下的代
码:
.text:00401000 ; *************** S U B R O U T I N E ***************************************
.text:00401000
.text:00401000
.text:00401000 sub_401000 proc near ; DATA XREF: .rdata:off_4021C0o
.text:00401000 mov eax, ds:AFX_MSGMAP const CWinApp::messageMap
.text:00401005 retn
.text:00401005
.text:00401005 sub_401000 endp
恰恰是一个返回基类的MessageMap的函数。因此我们也同样有理由假设"off_4021C0就是一个MessageMap数据"。
对于虚函数表的假设是如何被证明呢?首先我们要知道关于虚函数表的一点知识:虚函数表由虚函数的地址组成,表中函数
地址的顺序和它们第一次出现的顺序(即在类定义的顺序)一致。若有重载的函数,则替换掉基类函数的地址。通过这个我
们可以知道MFC中虚函数表中的函数顺序必然是先按照CObject-CCmdtarget-。。。。这个类继承顺序中的虚函数顺序来处
理虚函数表中的函数顺序的。只要证明这个我们"假设的虚函数"中的函数顺序与上面提到的知识相符合则有理由说明我们的
假设成立。
首先来看CObject中虚函数的顺序,在查看CObject的声明文件后得到了这个类的虚函数顺序:
virtual CRuntimeClass* GetRuntimeClass() const;
virtual ~CObject(); // virtual destructors are necessary
virtual void Serialize(CArchive ar);
#if defined(_DEBUG) || defined(_AFXDLL)
// Diagnostic Support
virtual void AssertValid() const;
virtual void Dump(CDumpContext dc) const;
再来查看CCmdtarget的虚函数顺序,在查看CObject的声明文件后得到了这个类的虚函数顺序:
DECLARE_DYNAMIC(CCmdTarget);
virtual BOOL OnCmdMsg(UINT nID, int nCode, void* pExtra,
AFX_CMDHANDLERINFO* pHandlerInfo);
#ifndef _AFX_NO_OLE_SUPPORT
// called when last OLE reference is released
virtual void OnFinalRelease();
#endif
#ifndef _AFX_NO_OLE_SUPPORT
// called before dispatching to an automation handler function
virtual BOOL IsInvokeAllowed(DISPID dispid);
virtual BOOL GetDispatchIID(IID* pIID);
virtual UINT GetTypeInfoCount();
virtual CTypeLibCache* GetTypeLibCache();
virtual HRESULT GetTypeLib(LCID lcid, LPTYPELIB* ppTypeLib);
之所以还要列出"DECLARE_DYNAMIC(CCmdTarget);"是因为这个宏的定义如下:
#define DECLARE_DYNAMIC(class_name) \
protected: \
static CRuntimeClass* PASCAL _GetBaseClass(); \
public: \
static const AFX_DATA CRuntimeClass class##class_name; \
virtual CRuntimeClass* GetRuntimeClass() const; \
这个virtual CRuntimeClass* GetRuntimeClass() const; 覆盖掉了一开始的CObject的相对应函数。依次按照类的顺序对
照下来,就可以知道该表确实是虚函数表。同时,对应的GetMessageMap虚函数的位置上跟入后,可以得到如下代码:
.text:00401010 ; *************** S U B R O U T I N E ***************************************
.text:00401010
.text:00401010
.text:00401010 sub_401010 proc near ; DATA XREF: .rdata:00402228o
.text:00401010 mov eax, offset off_4021C0
.text:00401015 retn
.text:00401015
.text:00401015 sub_401010 endp
恰恰是返回了我们之前假设的MessageMap的地址。
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!
用 CArchive 写入数据出错
参数CArchive::load表示是读的
需要CArchive::store才能写
可以写成CArchive::load|CArchive::store
vc/mfc-如下一段CArchive的代码出现了“没有找到未命名文件”的错误(Release,运行时出错)
有可能因为你使用了相对路径,当前路径应该是debug或者release文件夹,所以相对路径就找不到你指定的文件。
如何在c++中读取txt文件(最好有程序示例源代码)
#include iostream.h
#include fstream.h
#include stdlib.h
int main()
{
char buffer[256];
ifstream fliename("1.txt");
if(!fliename.is_open())
{
cout"Error opening file";
exit(1);
}
while(!fliename.eof())
{
fliename.getline(buffer,100);
coutbufferendl;
}
return 0;
}
当然你要是在MFC中的直接用CArchive;
CFile file(filename,CFile::modeCreate|CFile::modeWrite);
CArchive stor(file,CArchive::store);
storn_SaveData_MGS;
上面的存数据;
CFile file(Filename,CFile::modeRead);
CArchive textfile(file,CArchive::load);
CString data;
textfiledata;
这个是读数据,很方便
如何使用CArchive类把一个树结构序列化到外存呢
copy过来的,应该能解决你的问题。
原文
本文主要研究了一下如何把树形结构的数据保存到文件并读取出来。为了更形象说明用了一个界面程序显示,程序用了model/view框架。
数据类
DataItem 就是保存在树形结构的基本数据。其最重要的保存数据的函数是SerialzeData
[cpp]
{
public:
DataItem(int id = 100,QString name = "root");
~DataItem();
void SetRoot(DataItem *root);
void SerialzeData(bool isSave,QDataStream stream);
void Clear();
void Init();
//protected:
int GetID()
{
return ID;
}
QString GetName()
{
return Name;
}
void SetID(int id)
{
ID = id;
}
void SetName(QString name)
{
Name = name;
}
int GetSize()
{
return dataVec.size();
}
void AddItem(DataItem *pItem);
void DeleteItem(DataItem *pItem);
void DeleteItem(int index);
DataItem *GetItem(int index);
DataItem *GetParent()
{
return pRoot;
}
int indexOf(DataItem* pItem);
private:
int ID;
QString Name;
vectorDataItem* dataVec;
DataItem *pRoot;
};
[cpp]
DataItem::DataItem( int id,QString name ):ID(id),Name(name),pRoot(NULL)
{
//pRoot = new DataItem(100,"Root");
}
DataItem::~DataItem()
{
}
//SerialzeData 原来是,保存数据时,先保存每个项的数据,在后面保存该项的子节点个数,并递归保存各个子节点数据
void DataItem::SerialzeData( bool isSave,QDataStream stream )
{
if (isSave)
{
streamGetID()GetName(); //save ID and Name
streamdataVec.size(); //save the number of child
for(int i = 0; i dataVec.size(); ++i)
{
dataVec[i]-SerialzeData(isSave,stream);
}
}
else
{
int id;
int size;
QString name;
streamidname; //Get ID and Name
SetID(id);
SetName(name);
streamsize; //Get the number of child
for(int i = 0; i size; ++i)
{
DataItem *pItem = new DataItem(0,"name");
pItem-SerialzeData(isSave,stream);
AddItem(pItem);
}
}
}
void DataItem::AddItem( DataItem *pItem )
{
pItem-SetRoot(this);
dataVec.push_back(pItem);
}
void DataItem::DeleteItem( DataItem *pItem )
{
vectorDataItem*::iterator it = dataVec.begin();
for (it; it != dataVec.end(); ++it)
{
if (*it == pItem)
{
dataVec.erase(it);
break;
}
}
}
void DataItem::DeleteItem( int index )
{
if (index dataVec.size())
{
vectorDataItem*::iterator it = dataVec.begin();
it = it + index;
dataVec.erase(it);
}
}
void DataItem::Init()
{
for (int i = 0; i 5; ++i)
{
DataItem *pItem = new DataItem(i,QString("child%1").arg(i));
pRoot-AddItem(pItem);
for (int j = 0; j 2; ++j)
{
DataItem *pChild = new DataItem(j,QString("grandchild%0 -%1").arg(i).arg(j));
pItem-AddItem(pChild);
}
}
}
void DataItem::SetRoot( DataItem *root )
{
pRoot = root;
}
void DataItem::Clear()
{
dataVec.clear();
}
DataItem * DataItem::GetItem( int index )
{
if (index dataVec.size())
{
return dataVec[index];
}
else
{
return NULL;
}
}
int DataItem::indexOf( DataItem* pItem )
{
int index = -1;
for (int i = 0; i dataVec.size(); ++i)
{
if (dataVec[i] == pItem)
{
index = i;
break;
}
}
return index;
}
数据模型
TreeDataModel的底层数据就是上面定义的DataItem。用这种视图/模型的编程方式可以尽量减少数据与界面的耦合性。由于继承了QAbstractItemModel。所以必须重写其中的五个纯虚函数columnCount (),data(),index (),parent ()和rowCount()。
[cpp]
class TreeDataModel:public QAbstractItemModel
{
Q_OBJECT
public:
TreeDataModel(QObject *parent = NULL);
~TreeDataModel();
void SetRoot(DataItem *pRoot)
{
m_pTreeData = pRoot;
}
QModelIndex parent ( const QModelIndex index ) const;
QVariant data ( const QModelIndex index, int role = Qt::DisplayRole ) const ;
QVariant headerData ( int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const;
QModelIndex index ( int row, int column, const QModelIndex parent = QModelIndex() ) const;
int columnCount ( const QModelIndex parent = QModelIndex() ) const;
int rowCount ( const QModelIndex parent = QModelIndex() ) const;
DataItem* dataFromIndex(const QModelIndex index) const;
void SaveData(QDataStream out);
void LoadData(QDataStream in);
protected:
private:
DataItem *m_pTreeData;
};
[cpp]
TreeDataModel::TreeDataModel( QObject *parent /*= NULL*/ ):QAbstractItemModel(parent)
{
m_pTreeData = NULL;
}
TreeDataModel::~TreeDataModel()
{
}
QVariant TreeDataModel::data( const QModelIndex index, int role /*= Qt::DisplayRole */ ) const
{
DataItem *pItem = dataFromIndex(index);
if ((pItem)(role == Qt::DisplayRole))
{
switch (index.column())
{
case 0:
return pItem-GetID();
case 1:
return pItem-GetName();
}
}
return QVariant();
}
QVariant TreeDataModel::headerData( int section, Qt::Orientation orientation, int role /*= Qt::DisplayRole */ ) const
{
if ((section 2) (orientation == Qt::Horizontal) (role == Qt::DisplayRole))
{
switch (section)
{
case 0:
return tr("编号");
case 1:
return tr("名称");
default:
return QVariant();
}
}
else
{
return QVariant();
}
}
QModelIndex TreeDataModel::index( int row, int column, const QModelIndex parent /*= QModelIndex() */ ) const
{
if (!m_pTreeData ||row 0 || column 0)
{
return QModelIndex();
}
else
{
DataItem *pItem = dataFromIndex(parent);
if (pItem)
{
DataItem *pChild = pItem-GetItem(row);
if (pChild)
{
return createIndex(row,column,pChild);
}
}
return QModelIndex();
}
}
int TreeDataModel::columnCount( const QModelIndex parent /*= QModelIndex() */ ) const
{
return 2;
}
int TreeDataModel::rowCount( const QModelIndex parent /*= QModelIndex() */ ) const
{
DataItem *pItem = dataFromIndex(parent);
if (pItem)
{
return pItem-GetSize();
}
return 0;
}
DataItem* TreeDataModel::dataFromIndex( const QModelIndex index ) const
{
if (index.isValid())
{
return static_castDataItem*(index.internalPointer());
}
else
{
return m_pTreeData; //这里不要返回NULL
}
}
QModelIndex TreeDataModel::parent( const QModelIndex index ) const
{
if (index.isValid())
{
DataItem *pItem = dataFromIndex(index);
if (pItem)
{
DataItem *pParent = pItem-GetParent();
if (pParent)
{
DataItem *pGrandParent = pParent-GetParent();
if (pGrandParent)
{
int row = pGrandParent-indexOf(pParent);
return createIndex(row,index.column(),pParent);
}
}
}
}
return QModelIndex();
}
void TreeDataModel::SaveData( QDataStream out )
{
m_pTreeData-SerialzeData(true,out);
}
void TreeDataModel::LoadData( QDataStream in )
{
m_pTreeData-SerialzeData(false,in);
}
主框架类
这个类主要实现左边的树形把数据保存到文件中,然后在右边的树形结构加载显示出来。
[cpp]
class MainWidget:public QWidget
{
Q_OBJECT
public:
MainWidget(QWidget *patent = NULL);
~MainWidget();
protected slots:
void leftSelectBtnSlot();
void rightSelectBtnSlot();
void saveBtnSlot();
void loadBtnSlot();
private:
QSplitter *m_pSplitter;
QTreeView *m_pLeftTreeView;
QTreeView *m_pRightTreeView;
QPushButton *m_pLeftSaveBtn;
QPushButton *m_pRightLoadBtn;
QPushButton *m_pLeftSelectBtn;
QPushButton *m_pRightSelectBtn;
QLineEdit *m_pLeftLEdit;
QLineEdit *m_pRightLEdit;
QGridLayout *m_pLeftLayout;
QGridLayout *m_pRightLayout;
TreeDataModel *m_pLeftModel;
TreeDataModel *m_pRightModel;
};
carchive源代码的介绍就聊到这里吧,感谢你花时间阅读本站内容,更多关于carve中文、carchive源代码的信息别忘了在本站进行查找喔。
版权说明:如非注明,本站文章均为 AH站长 原创,转载请注明出处和附带本文链接;
- 上一篇:隐藏导航代码(导航的隐藏功能)
- 下一篇:好代码举例说明(代码的例子)
相关推荐
- 05-12中文搜索引擎,最大的中文搜索引擎
- 05-07pb超级报表源代码(pb报表工具)[20240507更新]
- 05-07简历源代码可以上传照片的简单介绍[20240507更新]
- 05-07广告切换源代码免费下载(广告切换源代码免费下载安装)[20240507更新]
- 05-06阁楼网源代码(阁楼是什么网站)[20240506更新]
- 05-06源代码管理资源管理器(资源管理器运行代码)[20240506更新]
- 05-06人脸识别源代码pdf的简单介绍[20240506更新]
- 05-06包含超市管理系统java源代码的词条[20240506更新]
- 05-06商城app源代码免费(商城App源码)[20240506更新]
- 05-06包含游戏源代码不同的模式的词条[20240506更新]
取消回复欢迎 你 发表评论:
- 标签列表
- 最近发表
- 友情链接