程序侠源码
A. 求:手机软件源代码!
其实这里有很多的:
[gnokii-0.3.2.tar.gz]
Nokia手机工具程序。可以管理手机的电话薄,发送/接收短消息,查看电池状态等 (2001-02-14, UNIX, 731KB, 2130次)
[smslink-0.44b.tar.gz]
手机短消息服务的服务器和客户端 (2001-01-08, LINUX, 91KB, 1883次)
[移动短信SMS综合资料库.rar]
短消息基础知识;短消息的信息处理流程及其分析、解决问题的方法;手机短信息SMS开发—编码,解码;PDU介绍;短消息的体系结构等 (2005-09-28, CHM, 1009KB, 1536次)
[nle-0.0.1-2.tgz]
可以修改Nokia手机的logo图标的程序 (2001-02-14, LINUX, 21KB, 1442次)
[是男人就下一百层SHY.rar]
制作的第一款休闲类的手机游戏,适合初学者参考 (2005-06-15, java, 484KB, 1357次)
[sms_client-2.0.7k.tgz]
使用TAP的蜂窝型GSM手机短消息服务中心 (2001-01-08, LINUX, 82KB, 1333次)
[mobile_sms.zip]
使用手机发送短消息的编程方法 (2001-11-21, HTML, 5KB, 1174次)
[kvanttisms-src-0.5.tgz]
Java写的通过手机收发短信息的程序。 (2001-11-20, Java, 10KB, 1049次)
[BREW开发-海信(王宏兵).rar]
深入研究BREW手机游戏开发———— 王洪信开发者最好的初学资料 (2005-09-26, Visual C++, 7229KB, 841次)
[jSMSEngine_2_0_4.zip]
开源的手机短信开发包!包括例子程序和比较详细的文档,还有开发者的网站!来源于sourceforge! (2006-01-21, Java, 438KB, 729次)
[qrcode_js.zip]
手机内嵌二维条码图像识别的JAVA的源程序,强烈推荐下载。 (2006-01-14, Java, 2210KB, 677次)
[gprs_sms.zip]
一个用COM或USB接口连接gsm/gprs手机进行短信收发的程序,用到的是simense的通讯模块 (2003-02-20, Visual C++, 97KB, 629次)
[PaoPao.rar]
j2me手机泡泡龙游戏。写得不错还未完工的版本。不过可以用来学习。 (2005-03-04, Java, 83KB, 613次)
[MakeMap.rar]
用java写的地图编辑器,可用于j2me手机游戏的地图编辑。 (2005-03-04, Java, 26KB, 606次)
[J2mebox.rar]
一个类似打地鼠的j2me手机游戏。 (2005-03-04, Java, 58KB, 521次)
[shoujihaomachaxun.rar]
输入手机号码可查询:归属地址、手机号码、区号、所属卡型 (2006-06-05, Java, 686KB, 520次)
[rich_man+src.rar]
大富翁手机游戏。 (2005-03-04, Java, 269KB, 513次)
[gsmssend-1.6.tar.gz]
通过网站发送手机短信息的程序。需要GNOME/GTK支持 (2001-11-20, LINUX, 352KB, 498次)
[MTKstart.rar]
台湾联发(MTK)手机芯片资料,可作为手机应用的平台 (2007-08-09, C-C++, 118KB, 495次)
[C# 发短信.rar]
使用C#发短信,连接Modem或者手机,通过串口发送短信, (2004-06-30, CSharp, 437KB, 469次)
[WindowsMobile5.0.rar]
Windows Mobile 5.0 三十几个经典手机软件开发源码希望对大家有帮助. (2006-08-30, CSharp, 578KB, 449次)
[motorola_RingerToneFormat.zip]
motorola手机铃声格式文档 (2002-06-07, PDF, 45KB, 445次)
[ksiemens-0.1.tar.gz]
KDE下的西门子手机管理程序,如图标,电话薄,短信息等管理 (2001-11-21, LINUX, 3437KB, 444次)
[nec麻将.rar]
一个java编的小游戏.对初学手机游戏编程的人很有用啊. (2005-06-07, Java, 50KB, 434次)
[nokiacomposer.src.zip]
Nokia手机语音管理程序,如上载音乐等。 (2001-11-21, Visual C++, 315KB, 422次)
[SmartMessagingFAQ.zip]
诺基亚手机图片铃声开发文档 (2002-06-07, PDF, 23KB, 410次)
[motolora_smscertguide.zip]
motorola手机短信息开发文档 (2002-06-07, PDF, 134KB, 400次)
[MV100-0.1.rar]
是一个手机功能的模拟程序,从界面到功能都做了很好的模拟 (2005-07-29, C-C++, 14630KB, 384次)
[helix.src.0812.rar]
着名的 helix realplayer 基于手机 symbian 系统的 播放器全套源代码,内含编译工具、以及配套相关软件:WinCVS、Python等。花了近一个多月才整理完成,是非常难得的全套代码。 (2005-05-19, C++, 43787KB, 373次)
[eluosi方块.rar]
经典的手机游戏源码俄罗斯方块,基于C+Brew开发 (2005-07-14, C-C++, 425KB, 373次)
[MTK2.rar]
这是我上传MTK手机开发的一些资料2,这两天起上传6份资料,全部是手开发的。希望对你们有用。 (2007-04-13, C-C++, 5859KB, 371次)
[resource]
压缩包中一个为一般操作系统下的fft,一个是手机或类似设备中的T9拼音输入法 (2003-08-05, C-C++, 53KB, 359次)
[SeaHorse.rar]
手机游戏,画面效果还可以,可以作为手机游戏入门参考 (2005-06-15, Java, 273KB, 356次)
[nec 打飞机.rar]
一个JAVA编的小游戏,对初学手机游戏的人很有帮助. (2005-06-07, Java, 73KB, 335次)
[多级菜单.rar]
/*[原创]一个树形多级菜单参考程序 这是一个用于车载电话的菜单程序,可以看成是手机功能菜单的简化板. 我所认为的树形多级菜单是指:在一个父菜单项目下面有多个子菜单, 子菜单下面又有多个孙菜单...,进入下层菜单主要依*当前选中的索引.有点象文件的目录结构. 本木从前实现这类的菜单主要*分层的switch语句,每层都是一个switch.但当我看到晓奇大侠的 程序和耳朵灌满lq等人的争论后,那时那地,我的心境变化了,我意识到指针代表了先进的生产力, 代表了社会的发展方向,是建设和谐社会的必要条件.不管你用了多长时间C语言,只要你不善于用 一个小针指来指去,你就是那种"用嘴吃饭的高贵骑士,决不用屁股装弹步枪"的守旧分子和社会发 展的绊脚石.(跑题太远,删去1万字...打住) .言归正传,下面的程序适用CPU为Mega16,编译器为CVAVR 1.24.4a 由于按键数目较多,所以按键程 序把按键事件分为数字键,快捷键,确认键,取消键,上下翻键几类,以减小菜单结构的容量.一下菜单 数据在菜单结构数组中的偏移量,有多少个菜单象就有多少个宏定义*/ (2005-08-02, C-C++, 2KB, 334次)
[与小灵通讯的软件.zip]
手机的通讯,特别是小灵通的通讯,是非常难得的技术,也是很受欢迎的,快下啊! (2005-09-30, Visual C++, 39KB, 324次)
[C16汉字输入方案.rar]
“C16汉字输入方案”,是针对小键盘设备(如手机、遥控器等)通常为16个基本键(“0”到“9”、“*”、“#”、左右键、删除键、确认键)的情况,充分发掘16个键位条件下进行汉字输入和符号输入的潜力,使汉字、英文、数字输入达到尽可能高的效率,是在16键的小键盘设备进行汉字输入的优秀方案。 (2005-10-27, C++ Builder, 76KB, 316次)
[CDMA短消息发送程序.zip]
用vc开发的cdma手机模块收发短信的功能,主要部分是串口通信和gb->unicode码间的转换。 (2005-12-08, Visual C++, 193KB, 313次)
B. 跪求!asp网页在线观看视频源码~~~小妹刚学的 遇到困难 请各位大侠帮忙啊!多谢~~
程序代码
<object classid=\"clsid:22D6F312-B0F6-11D0-94AB-0080C74C7E95\" id=\"MediaPlayer1\" width=\"286\" height=\"225\">
<param name=\"AudioStream\" value=\"-1\">
<param name=\"AutoSize\" value=\"-1\">
<!--是否自动调整播放大小-->
<param name=\"AutoStart\" value=\"-1\">
<!--是否自动播放-->
<param name=\"AnimationAtStart\" value=\"-1\">
<param name=\"AllowScan\" value=\"-1\">
<param name=\"AllowChangeDisplaySize\" value=\"-1\">
<param name=\"AutoRewind\" value=\"0\">
<param name=\"Balance\" value=\"0\">
<!--左右声道平衡,最左-9640,最右9640-->
<param name=\"BaseURL\" value>
<param name=\"BufferingTime\" value=\"15\">
<!--缓冲时间-->
<param name=\"CaptioningID\" value>
<param name=\"ClickToPlay\" value=\"-1\">
<param name=\"CursorType\" value=\"0\">
<param name=\"CurrentPosition\" value=\"0\">
<!--当前播放进度 -1 表示不变,0表示开头 单位是秒,比如10表示从第10秒处开始播放,值必须是-1.0或大于等于0-->
<param name=\"CurrentMarker\" value=\"0\">
<param name=\"DefaultFrame\" value>
<param name=\"DisplayBackColor\" value=\"0\">
<param name=\"DisplayForeColor\" value=\"16777215\">
<param name=\"DisplayMode\" value=\"0\">
<param name=\"DisplaySize\" value=\"0\">
<!--视频1-50%, 0-100%, 2-200%,3-全屏 其它的值作0处理,小数则采用四舍五入然后按前的处理-->
<param name=\"Enabled\" value=\"-1\">
<param name=\"EnableContextMenu\" value=\"-1\">
<!-是否用右键弹出菜单控制-->
<param name=\"EnablePositionControls\" value=\"-1\">
<param name=\"EnableFullScreenControls\" value=\"-1\">
<param name=\"EnableTracker\" value=\"-1\">
<!--是否允许拉动播放进度条到任意地方播放-->
<param name=\"Filename\" value=\"http://www.lm533.com/music/lanmeng/01.mp3\" valuetype=\"ref\">销坦派
<!--播放的文件地址-->
<param name=\"InvokeURLs\" value=\"-1\">
<param name=\亏贺"Language\" value=\"-1\">
<param name=\"Mute\" value=\"0\">
<信派!--是否静音-->
<param name=\"PlayCount\" value=\"10\">
<!--重复播放次数,0为始终重复-->
<param name=\"PreviewMode\" value=\"-1\">
<param name=\"Rate\" value=\"1\">
<!--播放速率控制,1为正常,允许小数-->
<param name=\"SAMIStyle\" value>
<!--SAMI样式-->
<param name=\"SAMILang\" value>
<!--SAMI语言-->
<param name=\"SAMIFilename\" value>
<!--字幕ID-->
<param name=\"SelectionStart\" value=\"-1\">
<param name=\"SelectionEnd\" value=\"-1\">
<param name=\"SendOpenStateChangeEvents\" value=\"-1\">
<param name=\"SendWarningEvents\" value=\"-1\">
<param name=\"SendErrorEvents\" value=\"-1\">
<param name=\"SendKeyboardEvents\" value=\"0\">
<param name=\"SendMouseClickEvents\" value=\"0\">
<param name=\"SendMouseMoveEvents\" value=\"0\">
<param name=\"SendPlayStateChangeEvents\" value=\"-1\">
<param name=\"ShowCaptioning\" value=\"0\">
<!--是否显示字幕,为一块黑色,下面会有一大块黑色,一般不显示-->
<param name=\"ShowControls\" value=\"-1\">
<!--是否显示控制,比如播放,停止,暂停-->
<param name=\"ShowAudioControls\" value=\"-1\">
<!--是否显示音量控制-->
<param name=\"ShowDisplay\" value=\"0\">
<!--显示节目信息,比如版权等-->
<param name=\"ShowGotoBar\" value=\"0\">
<!--是否启用上下文菜单-->
<param name=\"ShowPositionControls\" value=\"-1\">
<!--是否显示往前往后及列表,如果显示一般也都是灰色不可控制-->
<param name=\"ShowStatusBar\" value=\"-1\">
<!--当前播放信息,显示是否正在播放,及总播放时间和当前播放到的时间-->
<param name=\"ShowTracker\" value=\"-1\">
<!--是否显示当前播放跟踪条,即当前的播放进度条-->
<param name=\"TransparentAtStart\" value=\"-1\">
<param name=\"VideoBorderWidth\" value=\"0\">
<!--显示部的宽部,如果小于视频宽,则最小为视频宽,或者加大到指定值,并自动加大高度.此改变只改变四周的黑框大小,不改变视频大小-->
<param name=\"VideoBorderColor\" value=\"0\">
<!--显示黑色框的颜色, 为RGB值,比如ffff00为黄色-->
<param name=\"VideoBorder3D\" value=\"0\">
<param name=\"Volume\" value=\"0\">
<!--音量大小,负值表示是当前音量的减值,值自动会取绝对值,最大为0,最小为-9640-->
<param name=\"WindowlessVideo\" value=\"0\">
<!--如果是0可以允许全屏,否则只能在窗口中查看-->
</object>
上面的这个播放器是老式的那种,新式播放器是在MediaPlayer9.0以后出现的,也就是说只有装了9.0或9.0以上的播放器才能正常使用的.
下面是新式播放器代码,相对以前的来说要简单很多:
程序代码
<object id=\"player\" height=\"64\" width=\"260\" classid=\"CLSID:6BF52A52-394A-11d3-B153-00C04F79FAA6\">
<param NAME=\"AutoStart\" VALUE=\"-1\">
<!--是否自动播放-->
<param NAME=\"Balance\" VALUE=\"0\">
<!--调整左右声道平衡,同上面旧播放器代码-->
<param name=\"enabled\" value=\"-1\">
<!--播放器是否可人为控制-->
<param NAME=\"EnableContextMenu\" VALUE=\"-1\">
<!--是否启用上下文菜单-->
<param NAME=\"url\" VALUE=\"http://www.lm533.com/music/lanmeng/01.mp3\">
<!--播放的文件地址-->
<param NAME=\"PlayCount\" VALUE=\"1\">
<!--播放次数控制,为整数-->
<param name=\"rate\" value=\"1\">
<!--播放速率控制,1为正常,允许小数,1.0-2.0-->
<param name=\"currentPosition\" value=\"0\">
<!--控件设置:当前位置-->
<param name=\"currentMarker\" value=\"0\">
<!--控件设置:当前标记-->
<param name=\"defaultFrame\" value=\"\">
<!--显示默认框架-->
<param name=\"invokeURLs\" value=\"0\">
<!--脚本命令设置:是否调用URL-->
<param name=\"baseURL\" value=\"\">
<!--脚本命令设置:被调用的URL-->
<param name=\"stretchToFit\" value=\"0\">
<!--是否按比例伸展-->
<param name=\"volume\" value=\"50\">
<!--默认声音大小0%-100%,50则为50%-->
<param name=\"mute\" value=\"0\">
<!--是否静音-->
<param name=\"uiMode\" value=\"mini\">
<!--播放器显示模式:Full显示全部;mini最简化;None不显示播放控制,只显示视频窗口;invisible全部不显示-->
<param name=\"windowlessVideo\" value=\"0\">
<!--如果是0可以允许全屏,否则只能在窗口中查看-->
<param name=\"fullScreen\" value=\"0\">
<!--开始播放是否自动全屏-->
<param name=\"enableErrorDialogs\" value=\"-1\">
<!--是否启用错误提示报告-->
<param name=\"SAMIStyle\" value>
<!--SAMI样式-->
<param name=\"SAMILang\" value>
<!--SAMI语言-->
<param name=\"SAMIFilename\" value>
<!--字幕ID-->
</object>
如果你看得懂上面的是什么东东的话,那就不会有问题了。把其中一个插入一个网页上,换一个媒体文件地址就能播这文件了,笨一点就可以每一集做一个文件,再加一个总的,也就是提供“点击”链接的页面。
C. 急!那位大侠有用C语言实现的互相关算法的源代码,谢谢啦
#include <math.h>
#define M_PI 3.14159265358979323846
#define FALSE 0
#define TRUE 1
#define BIG 1e10
#define SMALL 1e-10
typedef struct {
float r, i;
} complex;
/* FAST CORRELATION OF X(0:L) AND Y(0:L). FINDS RXY(0) THRU RXY(NMAX). */
/* L=LAST INDEX IN BOTH X AND Y. MUST BE (POWER OF 2)+1 AND AT LEAST 5. */
/* ITYPE=TYPE OF CORRELATION=0 IF X AND Y ARE THE SAME VECTOR (AUTO- */
/* CORRELATION), OR NOT 0 IF X AND Y ARE DIFFERENT VECTORS. */
/* NMAX=MAXIMUM LAG OF INTEREST IN THE CORRELATION FUNCTION. */
/* FFT LENGTH ,N, USED INTERNALLY, IS L-1. */
/* LET K=INDEX OF FIRST NONZERO SAMPLE IN Y(0)---Y(N-1). THEN X(0) */
/* 到 X(N-1) MUST INCLUDE PADDING OF AT LEAST NMAX-K ZEROS. */
/* CORRELATION FUNCTION, RXY, REPLACES X(0) THRU X(NMAX). */
/* Y(0) THRU Y(L) IS REPLACED BY ITS FFT, COMPUTED USING SPFFTR. */
/* IERROR=0 NO ERROR DETECTED */
/* 1 L-1 NOT A POWER OF 2 */
/* 2 NMAX OUT OF RANGE */
/* 3 INADEQUATE ZERO */
void spcorr(float *x, float *y, long *l, long *type, long *nmax, long *error)
/*
x:序列X;
y:序列Y;
l:序列X与序列Y的长度,不小5,且要为2的幂次方;
type:相关的类型,0:表示X与Y序列相同,其它值:X与Y序列不相同
nmax:相关的最大时延;
error:运行出错提示;0:无错;1:数据长度不是2的幂次方;2:时延超界;3:无足够零填充出错
*/
{
long j, k, m, n;//n:FFT长度;k:序列Y中的首个非零样本的位置序号;在序列Y中必须最少包含有(nmax-k)零填充。
complex cx;
float test;
n = *l - 1;
if (*nmax < 0 || *nmax >= n)
{
*error = 2;
return;
}
test = (float) n;
test /= 2.0;
while ((test - 2.0) > 0.0)
{
test /= 2.0;
}
if ((test - 2.0) == 0)
{
for (k = 0 ; k < n && y[k] == 0.0 ; ++k) ;
for (j = n - 1 ; j >= 0 && x[j] == 0.0 ; --j) ;
if ((n - 1 - j) < (*nmax - k))
{
*error = 3;
return;
}
spfftr(x, &n);//对X序列FFT变换
if (*type != 0)
{
spfftr(y, &n);//如果X、Y是相同序列,则对Y序列也进行FFT
}
for (m = 0 ; m <= (n / 2) ; ++m)
{
cx.r = x[m * 2] * y[m * 2] - -x[(m * 2) + 1] * y[(m * 2) + 1];
cx.i = x[m * 2] * y[(m * 2) + 1] + -x[(m * 2) + 1] * y[m * 2];
x[m * 2] = cx.r / n;
x[(m * 2) + 1] = cx.i / n;
}
spiftr(x, &n);
*error = 0;
}
else if ((test - 2.0) < 0.0)
{
*error = 1;
}
return;
} /* spcorr */
/* SPFFTR 11/12/85 */
/* FFT ROUTINE FOR REAL TIME SERIES (X) WITH N=2**K SAMPLES. */
/* COMPUTATION IS IN PLACE, OUTPUT REPLACES INPUT. */
/* INPUT: REAL VECTOR X(0:N+1) WITH REAL DATA SEQUENCE IN FIRST N */
/* ELEMENTS; ANYTHING IN LAST 2. NOTE: X MAY BE DECLARED */
/* REAL IN MAIN PROGRAM PROVIDED THIS ROUTINE IS COMPILED */
/* SEPARATELY ... COMPLEX OUTPUT REPLACES REAL INPUT HERE. */
/* OUTPUT: COMPLEX VECTOR XX(O:N/2), SUCH THAT X(0)=REAL(XX(0)),X(1)= */
/* IMAG(XX(0)), X(2)=REAL(XX(1)), ..., X(N+1)=IMAG(XX(N/2). */
/* IMPORTANT: N MUST BE AT LEAST 4 AND MUST BE A POWER OF 2. */
//FFT计算函数
void spfftr(complex *x, long *n)
{
/* Builtin functions */
void r_cnjg();
/* Local variables */
void spfftc();
long m, tmp_int;
complex u, tmp, tmp_complex;
float tpn, tmp_float;
tpn = (float) (2.0 * M_PI / (double) *n);
tmp_int = *n / 2;
spfftc(x, &tmp_int, &neg_i1);
x[*n / 2].r = x[0].r;
x[*n / 2].i = x[0].i;
for (m = 0 ; m <= (*n / 4) ; ++m)
{
u.r = (float) sin((double) m * tpn);
u.i = (float) cos((double) m * tpn);
r_cnjg(&tmp_complex, &x[*n / 2 - m]);
tmp.r = (((1.0 + u.r) * x[m].r - u.i * x[m].i)
+ (1.0 - u.r) * tmp_complex.r - -u.i * tmp_complex.i) / 2.0;
tmp.i = (((1.0 + u.r) * x[m].i + u.i * x[m].r)
+ (1.0 - u.r) * tmp_complex.i + -u.i * tmp_complex.r) / 2.0;
tmp_float = ((1.0 - u.r) * x[m].r - -u.i * x[m].i
+ (1.0 + u.r) * tmp_complex.r - u.i * tmp_complex.i) / 2.0;
x[m].i = ((1.0 - u.r) * x[m].i + -u.i * x[m].r
+ (1.0 + u.r) * tmp_complex.i + u.i * tmp_complex.r) / 2.0;
x[m].r = tmp_float;
r_cnjg(&x[*n / 2 - m], &tmp);
}
return;
} /* spfftr */
/* SPIFTR 02/20/87 */
/* INVERSE FFT OF THE COMPLEX SPECTRUM OF A REAL TIME SERIES. */
/* X AND N ARE THE SAME AS IN SPFFTR. IMPORTANT: N MUST BE A POWER */
/* OF 2 AND X MUST BE DIMENSIONED X(0:N+1) (REAL ARRAY, NOT COMPLEX). */
/* THIS ROUTINE TRANSFORMS THE OUTPUT OF SPFFTR BACK INTO THE INPUT, */
/* SCALED BY N. COMPUTATION IS IN PLACE, AS IN SPFFTR. */
//逆FFT变换函数
void spiftr(complex *x, long *n)
{
long m, tmp_int;
complex u, tmp_complex, tmp;
float tpn, tmp_float;
tpn = (float) (2.0 * M_PI / (double) *n);
for (m = 0 ; m <= (*n / 4) ; ++m)
{
u.r = (float) sin((double) m * tpn);
u.i = (float) -cos((double) m * tpn);
r_cnjg(&tmp_complex, &x[*n / 2 - m]);
tmp.r = ((1.0 + u.r) * x[m].r - u.i * x[m].i)
+ ((1.0 - u.r) * tmp_complex.r - -u.i * tmp_complex.i);
tmp.i = ((1.0 + u.r) * x[m].i + u.i * x[m].r)
+ ((1.0 - u.r) * tmp_complex.i + -u.i * tmp_complex.r);
r_cnjg(&tmp_complex, &x[*n / 2 - m]);
tmp_float = ((1.0 - u.r) * x[m].r - -u.i * x[m].i)
+ ((1.0 + u.r) * tmp_complex.r - u.i * tmp_complex.i);
x[m].i = ((1.0 - u.r) * x[m].i + -u.i * x[m].r)
+ ((1.0 + u.r) * tmp_complex.i + u.i * tmp_complex.r);
x[m].r = tmp_float;
r_cnjg(&x[*n / 2 - m], &tmp);
}
tmp_int = *n / 2;
spfftc(x, &tmp_int, &pos_i1);
return;
} /* spiftr *
void r_cnjg(complex *r, complex *z)
{
r->r = z->r;
r->i = -z->i;
}
D. 用什么软件来查看一个用Microsoft Visual C++ 6.0 编写的程序的源代码
标 题: MFC逆向初级研究(1)
作 者: 北斗之摇光
时 间: 2007-03-15 17:14
链 接: http://bbs.pediy.com/showthread.php?t=41087
详细信息:
【文章标题】: MFC逆向初级研究(1)
【文章作者】: 北斗之摇光
【作者邮箱】: [email protected]
【下载地址】: 自己搜索下载
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
引言
本文主要针对微软的VC++6.0中使用MFC产生的EXE文件的逆向研究,我曾经使用微软的Visual Studio 2005编译了一
个EXE文件,通过IDA反汇编以后发现该文件与VC++6.0产生的文件还是有所区别,因此特别在此声明一下。文中主要使用了I
DA pro 5.0和在看雪(www.pediy.com)下载的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的地址。
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!
E. java小游戏源代码
介绍这个给你把...我空间还有很多..
http://hi..com/282919088
importjava.applet.Applet;
importjava.applet.AudioClip;
importjava.awt.Dimension;
importjava.awt.Font;
importjava.awt.Toolkit;
importjavax.sound.sampled.AudioFileFormat;
importjavax.sound.sampled.AudioSystem;
importjavax.swing.JFrame;
importjavax.swing.JPanel;
importjava.awt.Rectangle;
importjavax.swing.BorderFactory;
importjavax.swing.JButton;
importjavax.swing.JOptionPane;
importjavax.swing.JSlider;
importjavax.swing.JLabel;
importjavax.swing.SwingUtilities;
importjavax.swing.UIManager;
importjavax.swing.event.ChangeEvent;
importjavax.swing.event.ChangeListener;
importjava.awt.event.ActionEvent;
importjava.awt.event.ActionListener;
importjava.awt.event.KeyAdapter;
importjava.awt.event.KeyEvent;
importjava.io.File;
importjava.util.Vector;
{
JPanelcontentPane;
JPaneljPanel1=newJPanel();
JButtonjButton1=newJButton();
JSliderjSlider1=newJSlider();
JLabeljLabel1=newJLabel();
JButtonjButton2=newJButton();
JLabeljLabel2=newJLabel();
intcount=1,rapidity=80;//count当前进行的个数,rapidity游标的位置
intzhengque=0,cuowu=0;
intrush[]={10,20,30};//游戏每关的个数可以自由添加.列{10,20,30,40,50}
intrush_count=0;//记录关数
charlist[]={'A','B','C','D','E','F','G','H','I','J','K','L',
'M','N','O','P','Q','R','S','T','U','V','W','X','Y',
'Z','1','2','3','4','5','6','7','8','9'};//随机出现的数字可以自由添加
Vectornumber=newVector();
Stringpaian="true";
AudioClipMusci_anjian,Music_shi,Music_chenggong;
publicFrame(){
try{
setDefaultCloseOperation(EXIT_ON_CLOSE);
//-----------------声音文件---------------------
Musci_anjian=Applet.newAudioClip(newFile("sounds//anjian.wav")
.toURL());
Music_shi=Applet.newAudioClip(newFile("sounds//shi.wav")
.toURL());
Music_chenggong=Applet.newAudioClip(newFile(
"sounds//chenggong.wav").toURL());
//---------------------------------------
jbInit();
}catch(Exceptionexception){
exception.printStackTrace();
}
}
/**
*Componentinitialization.
*
*@throwsjava.lang.Exception
*/
privatevoidjbInit()throwsException{
contentPane=(JPanel)getContentPane();
contentPane.setLayout(null);
setSize(newDimension(588,530));
setTitle("FrameTitle");
jPanel1.setBorder(BorderFactory.createEtchedBorder());
jPanel1.setBounds(newRectangle(4,4,573,419));
jPanel1.setLayout(null);
jButton1.setBounds(newRectangle(277,442,89,31));
jButton1.setText("开始");
jButton1.addActionListener(newFrame1_jButton1_actionAdapter(this));
jSlider1.setBounds(newRectangle(83,448,164,21));
jSlider1.setMaximum(100);
jSlider1.setMinimum(1);
jSlider1.setValue(50);
jLabel1.setText("速度");
jLabel1.setBounds(newRectangle(35,451,39,18));
jButton2.setBounds(newRectangle(408,442,89,31));
jButton2.setText("结束");
jButton2.addActionListener(newFrame1_jButton2_actionAdapter(this));
jLabel2.setText("第一关:100个");
jLabel2.setBounds(newRectangle(414,473,171,21));
contentPane.add(jPanel1);
contentPane.add(jButton2);
contentPane.add(jButton1);
contentPane.add(jSlider1);
contentPane.add(jLabel1);
contentPane.add(jLabel2);
this.addKeyListener(newMyListener());
jButton1.addKeyListener(newMyListener());
jSlider1.addKeyListener(newMyListener());
jSlider1.addChangeListener(newChangeListener(){
publicvoidstateChanged(ChangeEvente){
rapidity=jSlider1.getValue();
}
});
}
publicvoidrun(){
number.clear();
zhengque=0;
cuowu=0;
paian="true";
while(count<=rush[rush_count]){
try{
Threadt=newThread(newTthread());
t.start();
count+=1;
Thread.sleep(1000+(int)(Math.random()*2000));//生产下组停顿时间
//最快1快.最慢2秒
}catch(InterruptedExceptione){
e.printStackTrace();
}
}
while(true){//等待最后一个字符消失
if(number.size()==0){
break;
}
}
if(zhengque==0){//为了以后相除..如果全部正确或者错误就会出现错误.所以..
zhengque=1;
}
if(cuowu==0){
cuowu=1;
}
if(paian.equals("true")){//判断是否是自然结束
if(zhengque/cuowu>=2){
JOptionPane.showMessageDialog(null,"恭喜你过关了");
rush_count+=1;//自动加1关
if(rush_count<rush.length){
if(rapidity>10){//当速度大于10的时候在-5提加速度.怕速度太快
rapidity-=5;//速度自动减10毫秒
jSlider1.setValue(rapidity);//选择位置
}
Threadt=newThread(this);
t.start();
}else{
JOptionPane.showMessageDialog(null,"牛B...你通关了..");
rush_count=0;
count=0;
}
}else{
JOptionPane.showMessageDialog(null,"请再接再励");
rush_count=0;
count=0;
}
}else{
rush_count=0;
count=0;
}
}
publicvoidjButton1_actionPerformed(ActionEvente){
Threadt=newThread(this);
t.start();
}
publicvoidjButton2_actionPerformed(ActionEvente){
count=rush[rush_count]+1;
paian="flase";
}
{
publicvoidrun(){
booleanfo=true;
intY=0,X=0;
JLabelshow=newJLabel();
show.setFont(newjava.awt.Font("宋体",Font.PLAIN,33));
jPanel1.add(show);
X=10+(int)(Math.random()*400);
Stringparameter=list[(int)(Math.random()*list.length)]+"";
Beanbean=newBean();
bean.setParameter(parameter);
bean.setShow(show);
number.add(bean);
show.setText(parameter);
while(fo){
//---------------------数字下移--------------------
show.setBounds(newRectangle(X,Y+=2,33,33));
try{
Thread.sleep(rapidity);
}catch(InterruptedExceptione){
e.printStackTrace();
}
if(Y>=419){
fo=false;
for(inti=number.size()-1;i>=0;i--){
Beanbn=((Bean)number.get(i));
if(parameter.equalsIgnoreCase(bn.getParameter())){
cuowu+=1;
jLabel2.setText("正确:"+zhengque+"个,错误:"+cuowu
+"个");
number.removeElementAt(i);
Music_shi.play();
break;
}
}
}
}
}
}
{
publicvoidkeyPressed(KeyEvente){
Stringuu=e.getKeyChar()+"";
for(inti=0;i<number.size();i++){
Beanbean=((Bean)number.get(i));
if(uu.equalsIgnoreCase(bean.getParameter())){
zhengque+=1;
number.removeElementAt(i);
bean.getShow().setVisible(false);
jLabel2.setText("正确:"+zhengque+"个,错误:"+cuowu+"个");
Music_chenggong.play();
break;
}
}
Musci_anjian.play();
}
}
publicstaticvoidmain(String[]args){
try{
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}catch(Exceptionexception){
exception.printStackTrace();
}
Frameframe=newFrame();
DimensionscreenSize=Toolkit.getDefaultToolkit().getScreenSize();
DimensionframeSize=frame.getSize();
if(frameSize.height>screenSize.height){
frameSize.height=screenSize.height;
}
if(frameSize.width>screenSize.width){
frameSize.width=screenSize.width;
}
frame.setLocation((screenSize.width-frameSize.width)/2,
(screenSize.height-frameSize.height)/2);
frame.setVisible(true);
}
}
classFrame1_jButton2_{
privateFrameadaptee;
Frame1_jButton2_actionAdapter(Frameadaptee){
this.adaptee=adaptee;
}
publicvoidactionPerformed(ActionEvente){
adaptee.jButton2_actionPerformed(e);
}
}
classFrame1_jButton1_{
privateFrameadaptee;
Frame1_jButton1_actionAdapter(Frameadaptee){
this.adaptee=adaptee;
}
publicvoidactionPerformed(ActionEvente){
adaptee.jButton1_actionPerformed(e);
}
}
classBean{
Stringparameter=null;
JLabelshow=null;
publicJLabelgetShow(){
returnshow;
}
publicvoidsetShow(JLabelshow){
this.show=show;
}
publicStringgetParameter(){
returnparameter;
}
publicvoidsetParameter(Stringparameter){
this.parameter=parameter;
}
}