程序俠源碼
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;
}
}