HelperFunctions.h:
#pragma once
// General functions
string ToLower(string in);//到低位
int searchx(char *SearchBuff, int BuffSize, char *SearchString, int StringLen, char wc);//搜索char
bool GetWildcardBytePositions(string bytestring, vector<int>* wildcardpos);//獲取通配符字節指針
bool RgchContains(char* container, uint containerlen, char* containee, uint containeelen);
bool is_hex(string& s);//判斷hex
bool is_hexwild(string& s);//判斷hexwild
bool is_dec(string &s);//判斷dec
bool is_float(string &s);//判斷float
DWORD rev(DWORD dw);
bool split(vector<string> &vec, const string &str, const char delim);
char GetWildcard(string &s);//獲取通配符
int Str2Rgch(string &s, char* arr, uint size);//轉換字符串到rgch
int Str2RgchWithWC(string &s, char* arr, uint size, char wc);//轉換字符串到rgchWithWC
string trim(const string& sData);//去除前後空格字符
bool UnquoteString(string& s, char cstart, char cend);//結束字符串
void MsgBox(string sMsg, string sTitle);//消息框
void DbgMsg(int n, char* title);//調試消息
void DbgMsg(int n,string title="");
void DbgMsgHex(int n, char* title);
void DbgMsgHex(int n,string title="");
int Str2Hex(string &s, string &dst);//字符串轉換為Hex
int Str2Hex(string &s, string &dst, ulong size);
long double strtof(string &s);
int Int2Hex(DWORD dw, string &dst);//整型到hex
void ReplaceString(string &s, char* what, char* with);//替換字符串
string CleanString(string &s);//清除字符串
string Str2Unicode(char* s,ulong len);//轉換字符串到Unicode
string Str2Unicode(string &s);
bool ESPRun(void);//ESP運行
HWND hwndOllyDbg();//ollydbg句柄
HINSTANCE hinstModule();//模塊句柄
HWND FindHandle(DWORD dwThreadId, string wdwClass, long x, long y);//尋找句柄
// PE Dumper
bool SaveDump(string fileName, DWORD ep);//保存轉儲
bool GetPEInfo(DWORD ep);//獲取pe信息
DWORD resizeDW(DWORD dw, DWORD size);//重設大小雙字節
void resizeSTR(string &str, DWORD size);//重設大小字符串
string StrLastError(void);//最後錯誤
LARGE_INTEGER MyGetTickCount(ULONGLONG oldValue, bool bUseTickCount=0);//獲取Tick數
2011年10月2日星期日
2011年9月27日星期二
ODbgScript源碼學習(二十一)
void initLogWindow() {
//初始化記錄窗口
if (ollylang->wndLog.bar.nbar==0) {//如果語言工具條為空
ollylang->wndLog.bar.name[0]="Address"; //顯示地址字符串
ollylang->wndLog.bar.defdx[0]=9; //索引
ollylang->wndLog.bar.mode[0]=BAR_NOSORT; //模式為非分類
ollylang->wndLog.bar.name[1]="Message"; //消息
ollylang->wndLog.bar.defdx[1]=130; //索引
ollylang->wndLog.bar.mode[1]=BAR_NOSORT; //費分離
ollylang->wndLog.bar.nbar=2; //設置為2
ollylang->wndLog.mode=TABLE_COPYMENU|TABLE_APPMENU|TABLE_SAVEPOS|TABLE_ONTOP|TABLE_HILMENU; //模式為標籤複製菜單|添加菜單|保存指針|非頂部|HIL菜單
ollylang->wndLog.drawfunc=wndlog_get_text; //重畫函數為獲取文本
}
Quicktablewindow(&ollylang->wndLog,15,2,wndlogclass,"Script Log Window");
//快速表窗口
if (ollylang->wndLog.hw) { //如果句柄存在
HICON ico=LoadIcon(hinstModule(),MAKEINTRESOURCE(IDI_ICON_LOG));//加載圖標
SendMessage(ollylang->wndLog.hw,WM_SETICON,false,(long)ico);//發送設置圖標消息
// CloseHandle(ico);//關閉
}
}
int wndlog_sort_function(const t_sortheader *p1,const t_sortheader *p2,const int sort) {//分類函數
t_wndlog_data *lline1 = (t_wndlog_data *)p1; //行為分類頭數據指針
t_wndlog_data *lline2 = (t_wndlog_data *)p2;//行為分類頭數據指針
if (lline1->line > lline2->line)//如果行1大於行2
return 1; //則返回1
else if (lline1->line < lline2->line)
return -1;//否則返回-1
return 0; //默認返回0
}
int wndlog_get_text(char *s, char *mask, int *select, t_sortheader *ph, int column) {//獲取文本
unsigned int ret;
t_wndlog_data *lline = (t_wndlog_data *)ph;
t_dump *cpuasm; //定義轉儲類型變量
int p;
cpuasm = (t_dump *)Plugingetvalue(VAL_CPUDASM); //獲取插件值
ret = sprintf(s,"");
switch (column) {
case 0: //打印不同類型
ret = sprintf(s, "%X", lline->eip);
break;
case 1:
ret = sprintf(s, "%s", lline->message);
break;
}
if (!ret) ret=strlen(s); //如果打印長度不為0,賦值s的長度后返回
return ret;
}
void clearLogLines() {
if (!ollylang->tLogLines.empty()) {//如果數據不為空
Deletesorteddatarange(&(ollylang->wndLog.data),0,0xffffffff);//釋放記錄窗口數據0-0xffffffff
ollylang->tLogLines.clear(); //清除行
if (ollylang->wndLog.hw!=NULL) InvalidateRect(ollylang->wndLog.hw, NULL, FALSE); //重畫記錄窗口
}
}
int add2log(char* message) { //添加記錄
t_dump *cpuasm;
t_wndlog_data lline={0};
cpuasm = (t_dump *)Plugingetvalue(VAL_CPUDASM);
lline.line = ollylang->tLogLines.size()+1; //行為語言行大小加1
lline.eip = cpuasm->sel0;
lline.size = 1;
strncpy(lline.message,message,LOG_MSG_LEN-1);
ollylang->tLogLines.push_back(lline); //入棧
Addsorteddata(&(ollylang->wndLog.data),&(ollylang->tLogLines.back()));//添加數據
if (ollylang->wndLog.hw!=NULL) {
Selectandscroll(&ollylang->wndLog,lline.line-1,2);
InvalidateRect(ollylang->wndLog.hw, NULL, FALSE);
}
return 1;
}
int add2log(string & message) {
return add2log((char*)message.c_str());
}
int add2logMasked(char* message,char* mask) {
return 1;
}
标签:
源代碼,
ODbgScript源碼學習,
OllyDbg
2011年9月25日星期日
ODbgScript源碼學習(二十)
LogWindows.cpp:
LRESULT CALLBACK wndlog_winproc(HWND hw,UINT msg,WPARAM wp,LPARAM lp) {
t_logwnd_data *pll; //記錄數據結構定義
HMENU menu; //菜單
int i,shiftkey,controlkey;
switch (msg) {
case WM_DESTROY: //如果消息是
case WM_MOUSEMOVE:
case WM_LBUTTONDOWN:
case WM_LBUTTONDBLCLK:
case WM_LBUTTONUP:
case WM_RBUTTONDOWN:
case WM_RBUTTONDBLCLK:
case WM_HSCROLL:
case WM_VSCROLL:
case WM_TIMER:
case WM_SYSKEYDOWN: //如果是系統按鍵消息
Tablefunction(&ollylang->wndLog,hw,msg,wp,lp); //建立表函數
break; // 中斷Pass message to DefMDIChildProc()
// Custom messages responsible for scrolling and selection. User-drawn
// windows must process them, standard OllyDbg windows without extra
// functionality pass them to Tablefunction()
case WM_USER_SCR:
case WM_USER_VABS:
case WM_USER_VREL:
case WM_USER_VBYTE:
case WM_USER_STS:
case WM_USER_CNTS:
case WM_USER_CHGS:
case WM_WINDOWPOSCHANGED: //如果消息是重載
return Tablefunction(&ollylang->wndLog,hw,msg,wp,lp);//返回表函數
case WM_USER_MENU:
menu=CreatePopupMenu(); //如果是用戶菜單建立菜單
// AppendMenu(menu,MF_SEPARATOR,0,"-");//應用菜單
pll=(t_logwnd_data *)Getsortedbyselection(&(ollylang->wndLog.data),ollylang->wndLog.data.selected);//由選擇獲取分類數據
if (menu!=NULL && pll!=NULL) { //如果菜單句柄和記錄數據不為空
AppendMenu(menu,MF_DEFAULT, 10,"Clear");//增加清除菜單
// AppendMenu(menu,MF_STRING, 32,"Toggle Script BP\tF2");//增加中斷菜單
};
// Even when menu is NULL, call to Tablefunction is still meaningful.
i=Tablefunction(&ollylang->wndLog,hw,WM_USER_MENU,0,(LPARAM)menu);//表函數
if (menu!=NULL) DestroyMenu(menu);//釋放菜單
switch (i) {
case 10:
clearLogLines();//清除行
InvalidateRect(hw, NULL, FALSE);//重設客戶區
return 1;
default:;
}
return 0;
case WM_USER_DBLCLK:
pll=(t_wndlog_data *)Getsortedbyselection(&(ollylang->wndLog.data),ollylang->wndLog.data.selected);//獲取數據
if (pll!=NULL) {
if (pll->line) Setcpu(0,pll->line,0,0,CPU_ASMHIST|CPU_ASMCENTER|CPU_ASMFOCUS);//設置CPU窗口
InvalidateRect(hw, NULL, FALSE);//重設客戶區
return 1;
}
case WM_KEYDOWN:
shiftkey=GetKeyState(VK_SHIFT) & 0x8000;//獲取按鍵碼
controlkey=GetKeyState(VK_CONTROL) & 0x8000;
if (wp==VK_RETURN && shiftkey==0 && controlkey==0) {
// Return key follows in Disassembler.
pll=(t_wndlog_data *)Getsortedbyselection(&(ollylang->wndLog.data),ollylang->wndLog.data.selected);
if (pll!=NULL) {
if (pll->line) Setcpu(0,pll->line,0,0,CPU_ASMHIST|CPU_ASMCENTER|CPU_ASMFOCUS);//設置CPU窗口
InvalidateRect(hw, NULL, FALSE);
}
}
// else if (wp==VK_F2) { // && shiftkey==0 && controlkey==0) {
Tablefunction(&ollylang->wndLog,hw,msg,wp,lp);//表函數
break;
case WM_USER_CHALL:
case WM_USER_CHMEM:
InvalidateRect(hw, NULL, FALSE);
return 0;
case WM_PAINT:
Painttable(hw, &ollylang->wndLog, wndlog_get_text);//重畫表
return 0;
default:
break;
}
return DefMDIChildProc(hw,msg,wp,lp); //默認處理
}
标签:
源代碼,
ODbgScript源碼學習,
OllyDbg
2011年9月24日星期六
[轉載]BMW(ISA代碼)
作者:foxmain
;*******************************************************************************************************************
;*******************************************************************************************************************
org 0h ; 运行于BIOS中
db 55h,0AAh ; ISA模块头
db 15 ; 大小为 15*512字节
jmp MyROMCodeStart
;*******************************************************************************************************************
;*******************************************************************************************************************
;db 0bh
;db 6dh
;db 03h
times 18 db 0h
;dd 400020h,8b2e0060h,4e5590c0h
;dd a7164944h
;dd A7h
;db 44h,49h,16h
;db 167
;dd 2010000h,8000cc5h
dw 001ch; PCI數據結構起始偏移 00h
dw 0034h; PCI數據結構結束偏移 02h
dd 52494350h; PCIR(pci rom)標誌 04h
dw 10ech; 供應商ID 08h
dw 8139h; 設備ID(網卡8139) 0ah
dw 0000; 保留 0ch
dw 0018h; PCI數據結構長度 0eh
db 00h; PCI數據結構修訂版 10h
db 02,00,00; 類別代碼
dw 0008h; 代碼長度
dw 0201h; 代碼/數據修訂版本水平
db 00; 代碼類型(0表示可執行代碼)
db 80h; 指示字節
dw 0000h; 保留
dd 506e5024h,201h,6500h,0,20000h,6400h,0,0;
;*******************************************************************************************************************
;*******************************************************************************************************************
MyROMCodeStart:
pushf ;
pushad ;PCI設備規範中說明,除了返回值以外,其它的參數必需恢復
push es
push ds
; ret
cld
call x_code ; 跳轉到程序進入點
;*******************************************************************************************************************
;*******************************************************************************************************************
;------------------------------------------------------------------------
incbin "dst_sectors.dat";;;需要復制的數據
;------------------------------------------------------------------------
;*******************************************************************************************************************
;*******************************************************************************************************************
;oxfb9cd
;0xfb8ed
x_code:
pop ax
xor bx,bx
push bx
pop es
push cs
pop ds
mov si, ax
mov di, 7c00h
mov cx, 1c00h
rep movsb ;將需要復制的文件拷貝到7c00h處
mov ds,bx
mov ah, 41h
mov dl, 80h
mov bx, 55AAh
int 13h ;檢測是否支持擴展的BIOS int 13h功能
cmp bx, 0AA55h
jnz __Exit
test cl, 1
jz __Exit
call __Estimate_MBR;判斷MBR是否以經被HOOK
test ax,ax
jnz __Exit; 如果被HOOK了或者讀取錯誤退出
mov ax,7c00h
mov ecx,0
mov dx,14
call __Write_sectors
__Exit:
pop ds
pop es
popad
popf
retf
;*******************************************************************************************************************
;*******************************************************************************************************************
;=============================================================
; 需要將名稱變為大寫
; 輸入:ES:EDI = 字符串CX = 字符串長度(寬字符串)
;
;=============================================================
ToUpperCase:
PUSH ECX
PUSH EBX
XOR EBX,EBX
TEST CX,CX
JZ .End ; CX = 0
; 目前只處理 a-z => A-Z
.CheckNextChar:
CMP WORD[ES:EDI+EBX],0061H
JB .NextChar
CMP WORD[ES:EDI+EBX],007AH
JA .NextChar
; a < ch < z
SUB WORD[ES:EDI+EBX],20H
.NextChar:
; 繼續處理下一個字符
INC EBX
INC EBX
DEC CX
JNZ .CheckNextChar
.End:
; 返回
POP EBX
POP ECX
RET
;*******************************************************************************************************************
;*******************************************************************************************************************
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;function : write sectors
;vars : ax = offset of the buffer,dx = cnt of sectors to write,ecx = start sector No.
;data: 2009-5-23
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
__Write_sectors:
push si
push di
xor bx,bx
push bx
pop ds
mov si,97F0h
mov [word si],word 0010h
mov [word si+2],dx;寫dx個扇區的數據
mov [word si+4],ax
mov [word si+6],byte 0000h
mov [word si+8],ecx;從第ecx個扇區開始寫入
mov ecx,0004h
mov di,97FCh
_fill_zero1:
mov [byte di],byte 00h
inc di
loop _fill_zero1
mov ax,4300h
mov dl,80h
int 13h
jnb _normal_write
mov ax,0ffffh
_normal_write:
pop di
pop si
ret
;*******************************************************************************************************************
;*******************************************************************************************************************
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;function : __Estimate_MBR
;date : 2009-05-26
;if hooked return true else return false
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
__Estimate_MBR:
mov ax,0x8A00 ;7c00+e00
mov dx,1;需要讀取的扇區數
mov ecx,0;開始讀的起始扇區
push ax
call __Read_sectors;讀0扇區的內容
pop si
cmp ax,0xffff
jz _erro_read
mov ax,[word 0x8BFE] ;7c00+1FE
cmp ax,0xAA55
jnz FindSign
mov eax,[dword 0x8A92] ;7c00+e00+192
cmp eax,0x31746E69;;HOOK標誌
jz FindSign
mov ax,0
jmp NotHook
FindSign:
mov ax,1
jmp _erro_read
NotHook:
mov si,0x8B80 ;7c00+e00+180
mov di,0x7d80 ;7c00+180
mov cx,0x80
rep movsb ;複製分區表到0x7c00+0x180處
_erro_read:
ret
;*******************************************************************************************************************
;*******************************************************************************************************************
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;function : read sectors
;vars : ax = offset of the buffer,dx = cnt of sectors to read,ecx = start sector No.
;updata: 2009-5-23
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
__Read_sectors:
push si
push di
xor bx,bx
push bx
pop ds
mov si,97F0h
mov [word si],word 0010h
mov [word si+2],dx;讀取dx個扇區的數據
mov [word si+4],ax
mov [word si+6],byte 0000h
mov [word si+8],ecx ;從第ecx個扇區開始讀取。
mov ecx,0004h
mov di,97FCh
_fill_zero:
mov [byte di],byte 00h
inc di
loop _fill_zero
mov ax,4200h
mov dl,80h
int 13h
jnb _normal_read
mov ax,0ffffh
_normal_read:
pop di
pop si
ret
;*******************************************************************************************************************
;*******************************************************************************************************************
WaitPressScrollKey:
push ax
s0:
in al,60h
cmp al,0x46 ;Scroll Lock鍵掃描碼:46h
jnz s1
stc
pop ax
ret
s1:
in al,61h
test al,010h
jnz s2
con:
in al,61h
test al,10h
jz con
dec cx
s2:
or cx,cx
jnz s0
clc
pop ax
ret
times 7680-($-$$) db 0 ; 添加文件至7680字節大小
2011年9月20日星期二
ODbgScript源碼學習(十九)
LogWindows.h:
#define LOG_MSG_LEN TEXTLEN //定義記錄消息長度
// 腳本執行表This is the table for Script Execution
typedef struct t_wndlog_data {
unsigned long line; //行
unsigned long size; // 在地址空間由元素佔用大小Size occupied by element in address space
unsigned long type; // 數據元素類型Type of data element, TY_xxx
unsigned long eip; //當前地址eip
char message[LOG_MSG_LEN];
} t_logwnd_data; //記錄窗口數據結構
LRESULT CALLBACK wndlog_winproc(HWND hw,UINT msg,WPARAM wp,LPARAM lp); //指針回調函數記錄窗口的過程
void initLogWindow(); //初始化記錄窗口
int wndlog_sort_function(const t_sortheader *p1,const t_sortheader *p2,const int sort); //記錄窗口分類函數
int wndlog_get_text(char *s, char *mask, int *select, t_sortheader *ph, int column); //獲取文本
int add2log(string & command); //添加到記錄(字符串型)
int add2log(char * command); //添加到記錄(char型)
int add2logMasked(char* message,char* mask); //添加到記錄
void clearLogLines(); //清除記錄行
#define LOG_MSG_LEN TEXTLEN //定義記錄消息長度
// 腳本執行表This is the table for Script Execution
typedef struct t_wndlog_data {
unsigned long line; //行
unsigned long size; // 在地址空間由元素佔用大小Size occupied by element in address space
unsigned long type; // 數據元素類型Type of data element, TY_xxx
unsigned long eip; //當前地址eip
char message[LOG_MSG_LEN];
} t_logwnd_data; //記錄窗口數據結構
LRESULT CALLBACK wndlog_winproc(HWND hw,UINT msg,WPARAM wp,LPARAM lp); //指針回調函數記錄窗口的過程
void initLogWindow(); //初始化記錄窗口
int wndlog_sort_function(const t_sortheader *p1,const t_sortheader *p2,const int sort); //記錄窗口分類函數
int wndlog_get_text(char *s, char *mask, int *select, t_sortheader *ph, int column); //獲取文本
int add2log(string & command); //添加到記錄(字符串型)
int add2log(char * command); //添加到記錄(char型)
int add2logMasked(char* message,char* mask); //添加到記錄
void clearLogLines(); //清除記錄行
标签:
源代碼,
ODbgScript源碼學習,
OllyDbg
2011年9月18日星期日
[轉載]C++代碼分析
作 者: 鄧韜
時 間: 2011-08-25,14:29:18
鏈接: http://bbs.pediy.com/showthread.php?t=139289
C++虛函數是構成多態的一部分,多態指的是運行期決定調用哪個函數,下面是個純虛函數例子:
#include "stdafx.h"
class Test{
public:
Test(){
printf("Test::Test\n");
}
virtual ~Test(){
printf("Virtual ~Test()\n");
}
virtual void prointer()=0;
virtual void pointf()=0;
};
class TestA:public Test{
public:
TestA(){
printf("TestA::TestA\n");
}
virtual ~TestA(){
printf("TestA::TestA\n");
}
virtual void prointer(){
printf("Derive Class TestA::Pointer\n");
}
virtual void pointf(){
printf("Derive Class TestA::Pointf\n");
}
};
int _tmain(int argc, _TCHAR* argv[]){
TestA *pTest=new TestA;
pTest->pointf();
pTest->prointer();
delete pTest;
return 0;
}
這段代碼定義了一個抽像類,和一個派生類,抽像類不能創建自己的對象,但是可以間接的從派生類創建自己的對象,構成純虛函數的條件:
1. 一個類中必須要有一個虛函數
2. 在虛函數後面添加一個=0就是一個純虛函數了
抽象基類的所有純虛函數必須被派生類定義的虛函數覆蓋,否者派生類也是一個抽象基類,不能創建自己的對象;先看下Test類,由於Test類不能創建自己的對象,所以我根據TestA類來解析調用過程。 Test類我們可以把它看做一個地址,這個地址裡面有些指針,只想函數的地址,假如Test類的地址是0x401000,那麼在這個地址裡面的第一個就是虛折構函數,方便釋放類的對象的時候調用,第二個沒有了,因為我們只在Test類中定義一個析構函數,和一個構造函數,構造函數在編譯的時候就被編譯器從類的里面給趴到Main來了,看下反彙編代碼:
00401091 |. 6A 04 PUSH 4
00401093 |. E8 68000000 CALL <JMP.&MSVCR90.operator new>
00401098 |. 8BF0 MOV ESI,EAX
0040109A |. 83C4 04 ADD ESP,4
0040109D |. 85F6 TEST ESI,ESI
0040109F |. 74 27 JE SHORT 004010C8
這裡就是TestA *pTest=new TestA這裡了,從這段代碼我們可以看出,new是無論何如都會調用成功的,因為CALL <JMP.&MSVCR90.operator new>後的返回值,被比較是否等於0了,雖然這個比較不是我們的代碼,但是編譯器就已經夠定了new無論如何都會調用成功,如果CALL <JMP.&MSVCR90.operator new>的返回值是0,那麼構造函數都會被跳過,而構造函數是會被程序調用的,如果不調用的話,這樣就和C++構造函數的說法相反了,所以new 操作符分配的內存一定會成功的,我們在接著看下下面這段代碼:
004010A1 |. 57 PUSH EDI
004010A2 |. 8B3D B0204000 MOV EDI,DWORD PTR DS:[<&MSVCR90.printf>] ; msvcr90.printf
004010A8 |. 68 0C214000 PUSH 0040210C ; /format = "Test::Test"
004010AD |. C706 7C214000 MOV DWORD PTR DS:[ESI],0040217C ; |
004010B3 |. FFD7 CALL EDI ; \printf
004010B5 |. 68 2C214000 PUSH 0040212C ; ASCII "TestA::TestA"
004010BA |. C706 8C214000 MOV DWORD PTR DS:[ESI],0040218C
004010C0 |. FFD7 CALL EDI
這段代碼顯然是兩個類的構造函數被調用了,那麼其中傳遞了兩個地址給ESI,我們看下這個地址是什麼類容,我們跟隨到數據窗口看一下,顯示格式選擇為地址格式
0040217C 00401000 這就是這個地址的內容,一個代碼地址
C++構造.00401000其中第一個地址指向如下地址,跟隨一下
00401000 . 56 PUSH ESI
00401001 . 8BF1 MOV ESI,ECX
00401003 . 68 18214000 PUSH 00402118 ; /format = "Virtual ~Test()"
00401008 . C706 7C214000 MOV DWORD PTR DS:[ESI],0040217C ; |
0040100E . FF15 B0204000 CALL DWORD PTR DS:[<&MSVCR90.printf>] ; \printf
這裡顯然就是折夠函數了,所以當一個類中有虛析構函數的時候,這個虛析構函數的地址會被放在類指針的最前面,這裡把Test的地址的指針放入ESI裡面,然後根據ESP+8來判斷是否調用delete操作符,這些都是編譯器自動添加的,這是編譯器的事,我還沒那技術去研究
00401014 . 83C4 04 ADD ESP,4
00401017 . F64424 08 01 TEST BYTE PTR SS:[ESP+8],1
0040101C . 74 09 JE SHORT 00401027
0040101E . 56 PUSH ESI
0040101F . E8 D6000000 CALL <JMP.&MSVCR90.operator delete>
00401024 . 83C4 04 ADD ESP,4
00401027 > 8BC6 MOV EAX,ESI
00401029 . 5E POP ESI
0040102A . C2 0400 RETN 4
繼續我們上面的構造函數,類的構造函數被一次從上至下的調用之後,傳遞了Test和TestA的地址到ESI裡面,我們聲明的是TestA的對象,所以最後一個地址就是TestA了,看下反彙編代碼的調用過程
004010C2 |. 83C4 08 ADD ESP,8
004010C5 |. 5F POP EDI
004010C6 |. EB 02 JMP SHORT 004010CA
004010C8 |> 33F6 XOR ESI,ESI
004010CA |> 8B06 MOV EAX,DWORD PTR DS:[ESI] ;
004010CC |. 8B50 08 MOV EDX,DWORD PTR DS:[EAX+8]
004010CF |. 8BCE MOV ECX,ESI
004010D1 |. FFD2 CALL EDX
這裡ESI指向TestA類的起始地址,把這個起始地址傳到EAX裡面之後,就把這個類裡面的一個函數地址放到EDX裡面,TestA類本身一共有4個函數,剛才構造函數被外部也就是Main調用了,那麼裡面只剩下3個地址了,我們知道一個類如果有虛析構函數,第一個地址就指向虛析構函數的地址,EAX+8就是調用了
pTest->pointf();至於為什麼,自己想一下,MOV ECX,ESI通過ECX來保證堆棧的平衡
004010D3 |. 8B06 MOV EAX,DWORD PTR DS:[ESI] ; C++構造.0040218C
004010D5 |. 8B50 04 MOV EDX,DWORD PTR DS:[EAX+4]
004010D8 |. 8BCE MOV ECX,ESI
004010DA |. FFD2 CALL EDX
這裡就調用了pTest->prointer();因為我們是根據類的地址來決定調用哪個函數的
004010DC |. 8B06 MOV EAX,DWORD PTR DS:[ESI]
004010DE |. 8B10 MOV EDX,DWORD PTR DS:[EAX] ; C++構造.00401050
004010E0 |. 6A 01 PUSH 1
004010E2 |. 8BCE MOV ECX,ESI
004010E4 |. FFD2 CALL EDX
這裡就是調用TestA類的虛折構函數,也就是當前類的地址的第一個指針,我們跟踪進去看一下,下面是反彙編代碼:
00401050 . 56 PUSH ESI
00401051 . 57 PUSH EDI
00401052 . 8B3D B0204000 MOV EDI,DWORD PTR DS:[<&MSVCR90.printf>] ; msvcr90.printf
00401058 . 8BF1 MOV ESI,ECX
0040105A . 68 2C214000 PUSH 0040212C ; /format = "TestA::TestA"
0040105F . C706 8C214000 MOV DWORD PTR DS:[ESI],0040218C ; |
00401065 . FFD7 CALL EDI ; \printf
00401067 . 68 18214000 PUSH 00402118 ; ASCII "Virtual ~Test()"
0040106C . C706 7C214000 MOV DWORD PTR DS:[ESI],0040217C
00401072 . FFD7 CALL EDI
00401074 . 83C4 08 ADD ESP,8
00401077 . F64424 0C 01 TEST BYTE PTR SS:[ESP+C],1
0040107C . 74 09 JE SHORT 00401087
0040107E . 56 PUSH ESI
0040107F . E8 76000000 CALL <JMP.&MSVCR90.operator delete>
00401084 . 83C4 04 ADD ESP,4
00401087 > 5F POP EDI
00401088 . 8BC6 MOV EAX,ESI
0040108A . 5E POP ESI
0040108B . C2 0400 RETN 4
這裡調用了兩個虛析構函數的地方,為什麼是先調用~TestA,而不是先調用~Test呢,因為我們把這兩個析構函數定義為了虛函數,虛函數是在運行期決定調用誰的,當我們把TestA的成員函數調用完畢之後,析構函數會自動調用,因此,TestA完了之後就調用自己的析構函數,釋放最新分配的內存,所以,先調用TestA的折構函數,再調用Test的折構函數,這也是為什麼把析構函數聲明為虛函數的原因,
這裡調用了兩個虛析構函數之後,就是用delete指針刪除了由new分配的地址,分析完畢。
總結一下:
當我們定義了一個帶有虛函數的類的時候,這個類的虛函數就會被放在一個地址表裡面,這個地址表被放在類的入口裡面,當我們調用哪個類的時候,就使用哪個類的入口來調用裡面的虛函數,這就證名明了C++中得函數同名的虛函數的多態機制。
講得不好,如果有錯誤的地方請各位指出來,謝謝!
2011年9月16日星期五
[轉載]簡單的函數逆向(還原)
作 者: 天高
時 間: 2011-09-02,01:15:29鏈接: http://bbs.pediy.com/showthread.php?t=139643
看過論壇的一些關於逆向的貼子
說說我的看法:逆向工程並不是對代碼進行分析就算了,實際上要對工程進行一定的還原(源代碼形式),當然難度挺大,要對算法非常熟悉。要係統的數據結構非常熟悉,才有能力推還原工程的數據結構。
這裡僅對一個簡短的函數進行還原,當然並不可能還原為原作者源代碼,是還原為在函數的邏輯思想上最接近的形式。
代碼:
ntdll!memcpy_s:
00000000`77abee8c 48895c2408 mov qword ptr [rsp+8],rbx
00000000`77abee91 4889742410 mov qword ptr [rsp+10h],rsi
00000000`77abee96 57 push rdi
00000000`77abee97 4883ec30 sub rsp,30h
00000000`77abee9b 498bd9 mov rbx,r9
00000000`77abee9e 498bf0 mov rsi,r8
00000000`77abeea1 488bfa mov rdi,rdx
00000000`77abeea4 4d85c9 test r9,r9
00000000`77abeea7 7504 jne ntdll!memcpy_s+0x21 (00000000`77abeead)
ntdll!memcpy_s+0x1d:
00000000`77abeea9 33c0 xor eax,eax
00000000`77abeeab eb1c jmp ntdll!memcpy_s+0x3d (00000000`77abeec9)
ntdll!memcpy_s+0x21:
00000000`77abeead 4885c9 test rcx,rcx
00000000`77abeeb0 7527 jne ntdll!memcpy_s+0x4d (00000000`77abeed9)
ntdll!memcpy_s+0x26:
00000000`77abeeb2 48214c2420 and qword ptr [rsp+20h],rcx
00000000`77abeeb7 4533c9 xor r9d,r9d
00000000`77abeeba 4533c0 xor r8d,r8d
00000000`77abeebd 33d2 xor edx,edx
00000000`77abeebf e85c95ffff call ntdll!invalid_parameter (00000000`77ab8420)
ntdll!memcpy_s+0x38:
00000000`77abeec4 b816000000 mov eax,16h
ntdll!memcpy_s+0x3d:
00000000`77abeec9 488b5c2440 mov rbx,qword ptr [rsp+40h]
00000000`77abeece 488b742448 mov rsi,qword ptr [rsp+48h]
00000000`77abeed3 4883c430 add rsp,30h
00000000`77abeed7 5f pop rdi
00000000`77abeed8 c3 ret
ntdll!memcpy_s+0x4d:
00000000`77abeed9 4d85c0 test r8,r8
00000000`77abeedc 7412 je ntdll!memcpy_s+0x64 (00000000`77abeef0)
ntdll!memcpy_s+0x52:
00000000`77abeede 483bd3 cmp rdx,rbx
00000000`77abeee1 720d jb ntdll!memcpy_s+0x64 (00000000`77abeef0)
ntdll!memcpy_s+0x57:
00000000`77abeee3 4c8bc3 mov r8,rbx
00000000`77abeee6 488bd6 mov rdx,rsi
00000000`77abeee9 e8e2f7fbff call ntdll!memcpy (00000000`77a7e6d0)
00000000`77abeeee ebb9 jmp ntdll!memcpy_s+0x1d (00000000`77abeea9)
ntdll!memcpy_s+0x64:
00000000`77abeef0 4c8bc2 mov r8,rdx
00000000`77abeef3 33d2 xor edx,edx
00000000`77abeef5 e8d63ffcff call ntdll!memset (00000000`77a82ed0)
00000000`77abeefa 4885f6 test rsi,rsi
00000000`77abeefd 7505 jne ntdll!memcpy_s+0x78 (00000000`77abef04)
ntdll!memcpy_s+0x73:
00000000`77abeeff 8d5e16 lea ebx,[rsi+16h]
00000000`77abef02 eb0a jmp ntdll!memcpy_s+0x82 (00000000`77abef0e)
ntdll!memcpy_s+0x78:
00000000`77abef04 483bfb cmp rdi,rbx
00000000`77abef07 73bb jae ntdll!memcpy_s+0x38 (00000000`77abeec4)
ntdll!memcpy_s+0x7d:
00000000`77abef09 bb22000000 mov ebx,22h
ntdll!memcpy_s+0x82:
00000000`77abef0e 488364242000 and qword ptr [rsp+20h],0
00000000`77abef14 4533c9 xor r9d,r9d
00000000`77abef17 4533c0 xor r8d,r8d
00000000`77abef1a 33d2 xor edx,edx
00000000`77abef1c 33c9 xor ecx,ecx
00000000`77abef1e e8fd94ffff call ntdll!invalid_parameter (00000000`77ab8420)
00000000`77abef23 8bc3 mov eax,ebx
00000000`77abef25 eba2 jmp ntdll!memcpy_s+0x3d (00000000`77abeec9)
這是windows 7 64 位系統上ntdll 模塊的一個非常簡短的函數memcpy_s() ,結果並不重要,重要的是過程
1. 確定函數的參數個數
在64 位windows 系統上,函數的傳遞方式相對簡單,統一使用寄存器進行傳遞參數,分別使用:rcx, rdx, r8 以及r9 寄存器來傳遞前4 個參數,多餘的參數依舊使用stack 來傳遞。
在這個函數中,我們看到使用到了r9 寄存器,因此,我們可以判斷這個函數共有4 個參數,下面是memcpy_s() 函數的原型初形:
memcpy_s(arg1, arg2, arg3, arg4)
分別用arg1 - arg4 來表示,函數的返回值先暫時放一邊,隨著分析過程的展開進行填補。
2. 第 4 個參數的處理
下面看看代碼:
00000000`77abeea4 4d85c9 test r9,r9 ; arg4
00000000`77abeea7 7504 jne ntdll!memcpy_s+0x21 (00000000`77abeead)
ntdll!memcpy_s+0x1d:
00000000`77abeea9 33c0 xor eax,eax ; 返回值
00000000`77abeeab eb1c jmp ntdll!memcpy_s+0x3d (00000000`77abeec9)
... ...
ntdll!memcpy_s+0x3d:
00000000`77abeec9 488b5c2440 mov rbx,qword ptr [rsp+40h]
00000000`77abeece 488b742448 mov rsi,qword ptr [rsp+48h]
00000000`77abeed3 4883c430 add rsp,30h
00000000`77abeed7 5f pop rdi
00000000`77abeed8 c3 ret
從上面可以看到,這裡先判斷arg4 參數,如果為0 的話,它最終將會函數返回。
於是,我們可以得到下面的邏輯:
代碼:
if (arg4 == 0)
return 0;
3. 第 1 個參數的處理
下面看代碼:
ntdll!memcpy_s+0x21:
00000000`77abeead 4885c9 test rcx,rcx
00000000`77abeeb0 7527 jne ntdll!memcpy_s+0x4d (00000000`77abeed9)
ntdll!memcpy_s+0x26:
00000000`77abeeb2 48214c2420 and qword ptr [rsp+20h],rcx
00000000`77abeeb7 4533c9 xor r9d,r9d
00000000`77abeeba 4533c0 xor r8d,r8d
00000000`77abeebd 33d2 xor edx,edx
00000000`77abeebf e85c95ffff call ntdll!invalid_parameter (00000000`77ab8420)
ntdll!memcpy_s+0x38:
00000000`77abeec4 b816000000 mov eax,16h
ntdll!memcpy_s+0x3d:
00000000`77abeec9 488b5c2440 mov rbx,qword ptr [rsp+40h]
00000000`77abeece 488b742448 mov rsi,qword ptr [rsp+48h]
00000000`77abeed3 4883c430 add rsp,30h
00000000`77abeed7 5f pop rdi
00000000`77abeed8 c3 ret
如果,第1 個參數arg1 為0 的話,它將調用invalid_parameter() 函數,返回一個代碼值(返回狀態!)
invalid_parameter() 調用用先將rdx, r8 以及r9 寄存清0,那麼這裡我姑且認為它也是4 個參數(注意:這裡使用了edx, r8d 和r9d 寄存器,說明這些參數是32 位值)並且我們知道memcpy_s() 函數應該是返回一個狀態值!
現在,我們又可以得出它的邏輯(結果起來):
代碼:
STATUS memcpy_s(arg1, arg2, arg3, arg4)
{
if (arg4 == 0)
return 0;
if (arg1 == 0)
{
invalid_parameters(arg1, 0, 0, 0);
return 0x16; // 狀態值
}
}
3. 第 3 個參數的處理
假如,第1 個參數arg1 不為0 的時候呢?
ntdll!memcpy_s+0x21:
00000000`77abeead 4885c9 test rcx,rcx
00000000`77abeeb0 7527 jne ntdll!memcpy_s+0x4d (00000000`77abeed9)
... ...
ntdll!memcpy_s+0x4d:
00000000`77abeed9 4d85c0 test r8,r8 ; 第3 個參數
00000000`77abeedc 7412 je ntdll!memcpy_s+0x64 (00000000`77abeef0)
... ...
ntdll!memcpy_s+0x64:
00000000`77abeef0 4c8bc2 mov r8,rdx ; rdx 寄存器的值為arg2
00000000`77abeef3 33d2 xor edx,edx
00000000`77abeef5 e8d63ffcff call ntdll!memset (00000000`77a82ed0)
00000000`77abeefa 4885f6 test rsi,rsi
00000000`77abeefd 7505 jne ntdll!memcpy_s+0x78 (00000000`77abef04)
它將接下來判斷第3 個參數arg3,如果arg3 也為0 的時候,它將調用memset()
我們知道memset() 是置memory buffer 為某一值的作用,上面所示,它的參數有3 個,它的邏輯為:
代碼:
memset(char *dest, char c, unsigned int count)
在這個函數的調用中,我們可以知道rdx 寄存器將是傳遞給memset() 函數作為第3 個參數,而rcx 寄存器正是目標地址值,於是,我們知道memcpy_s() 函數的第1 個參數是目標地址值!
於是,我們在這裡可以得出:
代碼:
NT_STATUS memcpy_s(char *dest, arg2, arg3, arg4)
{
if (arg4 == 0) return 0;
if (arg1 == 0) {
invalid_argeter(arg1, 0, 0, 0)
return 0x16;
}
if (arg3 == 0) {
memset(dest,0, arg2);
invalid_argeter(arg1, 0, 0, 0)
return 0x16;
}
}
在這一步,我們得出了memcpy_s() 函數的第1 個參數,紅色標註的。
5. 第 2 個參數與第 4 個參數處理
當第3 個參數不為0 的時候,將會繼續判斷第2 個和第3 個參數:
ntdll!memcpy_s+0x52:
00000000`77abeede 483bd3 cmp rdx,rbx ; arg2 與arg4 之間的比較
00000000`77abeee1 720d jb ntdll!memcpy_s+0x64 (00000000`77abeef0)
... ...
ntdll!memcpy_s+0x64:
00000000`77abeef0 4c8bc2 mov r8,rdx
00000000`77abeef3 33d2 xor edx,edx
00000000`77abeef5 e8d63ffcff call ntdll!memset (00000000`77a82ed0)
00000000`77abeefa 4885f6 test rsi,rsi ; 關鍵一步, rsi 的值就是r8 也就是arg1
00000000`77abeefd 7505 jne ntdll!memcpy_s+0x78 (00000000`77abef04)
... ...
ntdll!memcpy_s+0x78:
00000000`77abef04 483bfb cmp rdi,rbx
00000000`77abef07 73bb jae ntdll!memcpy_s+0x38 (00000000`77abeec4)
ntdll!memcpy_s+0x7d:
00000000`77abef09 bb22000000 mov ebx,22h
ntdll!memcpy_s+0x82:
00000000`77abef0e 488364242000 and qword ptr [rsp+20h],0
00000000`77abef14 4533c9 xor r9d,r9d
00000000`77abef17 4533c0 xor r8d,r8d
00000000`77abef1a 33d2 xor edx,edx
00000000`77abef1c 33c9 xor ecx,ecx
00000000`77abef1e e8fd94ffff call ntdll!invalid_parameter (00000000`77ab8420)
00000000`77abef23 8bc3 mov eax,ebx
00000000`77abef25 eba2 jmp ntdll!memcpy_s+0x3d (00000000`77abeec9
這里通過比較arg2 與arg4 的大小,當arg2 小於arg4 的時候,同樣調用memset(),然後置狀態值0x22,然後返回。
在這一步,我們得到:
代碼:
NT_STATUS memcpy_s(char *dest, arg2, arg3, arg4)
{
if (arg4 == 0) return 0;
if (arg1 == 0) {
invalid_pargeter(dest, 0, 0, 0)
return 0x16;
}
if (arg3 == 0) {
memset(dest,0, arg2);
invalid_pargeter(dest, 0, 0, 0)
return 0x16;
}
if (arg2 < arg4)
{
memset(dest, 0, arg2);
invalid_pargeter(dest, 0, 0, 0)
return 0x22;
}
}
6. 最後一步,確定 arg2,arg3 以及 arg4
看下面最終的 memcpy() 代碼:
ntdll!memcpy_s+0x57:
00000000`77abeee3 4c8bc3 mov r8,rbx ; arg4 是size
00000000`77abeee6 488bd6 mov rdx,rsi ; r8 是source
00000000`77abeee9 e8e2f7fbff call ntdll!memcpy (00000000`77a7e6d0)
00000000`77abeeee ebb9 jmp ntdll!memcpy_s+0x1d (00000000`77abeea9)
最終將會調用memcpy() 進行複制,我們知道memcpy() 的原型大概是這樣的:
代碼:
memcpy(char *dest, char *source, unsinged int size)
這裡,我們明確的答案了, arg4 將會是size,arg3 將會是source
那麼,arg2 是什麼呢?通過前面的if (arg2 < arg4) 的比較,我們可以斷定,arg2 是buffer size,如果buffer size 小於count size 值時,那會將會出錯。
因此,最後一步,我們得到完全的邏輯:
代碼:
NT_STATUS memcpy_s(char *dest, arg2, arg3, arg4)
{
if (arg4 == 0) return 0;
if (arg1 == 0) {
invalid_argeter(dest, 0, 0, 0)
return 0x16;
}
if (arg3 == 0) {
memset(dest,0, arg2);
invalid_argeter(dest, 0, 0, 0)
return 0x16;
}
if (arg2 < arg4)
{
memset(dest, 0, arg2);
invalid_argeter(dest, 0, 0, 0)
return 0x22;
}
memcpy(dest, arg3, arg4);
return 0;
}
7. 最後,我們整理一下代碼,得出最終的一個結果:
下面是還原的結果,這不是原始源代碼,只是按照函數的邏輯形成的一個功能和邏輯一樣的代碼:
代碼:
STATUS memcpy_s(char *dest, unsigned int buffer_size, char *source, unsigned int count)
{
STATUS status = STATUS_SUCCESS;
if (count == 0)
return status;
if (dest == NULL)
{
status = STATUS_INVALID_ADDRESS;
}
else if (source == NULL)
{
memset(dest, 0, buffer_size);
status = STATUS_INVALID_ADDRESS;
}
else if (buffer_size < count)
{
memset(dest, 0, buffer_size);
status = STATUS_INVALID_BUFFER_SIZE;
}
else
memcpy(dest, source, count);
if (status != STATUS_SUCCESS)
invalid_parameter(dest, 0, 0, 0);
return status;
}
當然請注意:這裡的status 值是一個表述,在這裡不是真實的常量
2011年9月12日星期一
[轉載]也來說說ReactOS的調試
作 者:ProgmBoy
時 間:2009-02-16 22:36鏈接:http://bbs.pediy.com/showthread.php?t=82194
By::ProgrammeBoy
Blog:http://hi.baidu.com/ProgrammeBoy
老鳥飛過,科普類….有錯的地方大家別笑,
看ReactOS的源碼好多天了,許多windows下不明白的地方看看ReactOS的代碼也就知道差不多了...寫ReactOS的同志們可真是好人呀.想看linux但是還的學那一大堆命令....使用看reactos,照樣可以理解操作系統的精髓...還有就是編譯reactos在windows下,方便呀...,
廢話不多說,看了半天的reactos的代碼,心裡躍躍欲試,想為reactos做點貢獻,但是前提是怎麼調試代碼呢?.. ....由於網上關於reactos的調試很少...reactos的wiki上只有寥寥無幾的幾篇,也只是介紹內核調試器的使用..作為菜鳥的我只知道他是用9幀串口來傳輸數據.並不知道用什麼來接收調試數據.和發送調試命令,在群裡看的老蔡的使用的調試工具是:
總覺得不好使......自己嘗試著瞎整..還真找出了點路子.(鑑於是自己瞎整,錯誤的概率也就很大,此文的目的是為調試reactos提供一個方向)
在reactos的論壇上搜"調試"的時候知道源碼中有個fDebug是好像是用來調試的.所以我就找了先下fDebug的的代碼.在D:\ReactOS\ReactOS_src\boot\freeldr\fdebug這個目錄下.
這裡我嗦下.源代碼的路徑別放到目錄中有空格的文件夾中,有時會導致不能編譯.例如,以前我把源碼放在了D:\Program Files\ReactOS_src\boot\freeldr\fdebug這個目錄下,在編譯時可能會發生錯誤.(至於為什麼?我就不嗦了)
好了,回到正題.接下來就是編譯fDebug...,看了下fDebug的模塊名(怎麼看?打開fDebug下的fDebug.rbuild文件裡面有個module name=的字樣,後面的就是)當時我隨手打開了編譯環境,輸入"makex freeldr_fdebug",可是提示,mingw32-make: *** No rule to make target `fDebug'. Stop.,沒有次模塊,打開配置文件D:\ReactOS\ReactOS_src\boot\ freeldr\freeldr.rbuild,發現並沒有fDebug,那我們自己填,怎麼填?嗯是個問題.
follow me:來到這個模塊所在的主目錄下也就是D:\Program Files\ReactOS_src\boot\freeldr\,找到freeldr.rebuild文件打開添加下面的:
代碼:
<directory name="fdebug">
<xi:include href="fdebug/fdebug.rbuild" />
</directory>
然後在編譯環境下再次輸入: makex freeldr_fdebug.等了會,出現
代碼:
[LD] output-i386\boot\freeldr\fdebug\fdebug.exe
[RSYM] output-i386\boot\freeldr\fdebug\fdebug.exe
的字樣OK編譯好了,我們在運行下:
這裡有兩個問題:
1,在哪運行呀?如果在windows下兼容嗎?
2,文件在哪呀?
答:(1)在windows下,因為我們要在windows下用fDebug和虛擬機調試,可能還會有人問兼容嘛?由於reactos設計的宗旨就是兼容windows,所以,reactos的應用程序幾乎都能在windows下運行!,而相反就不一定了,畢竟還在開發中嘛..
(2)文件在哪?正如編譯環境給你列出來的D:\ReactOS\ReactOS_src\ output-i386\boot\freeldr\fdebug\fdebug.exe下就能找到
編譯好了,我們來調試吧,先嗦下,調試環境,我類似於windbg + Vmware, 首先在虛擬機中裝ReactOS,怎麼裝我就不再嗦了,他的老家的論壇上有,然後打開虛擬機的設置->添加硬件-->串口使用命名管道..其餘默認就行..
呵呵,開始調試嘍,打開虛擬機.以調試模式運行Reactos(就是一進系統有好幾個選項我們選第二個(即ReactOS (Debug))),打開fDebug,如圖:
唉,白呀,打開”文件””Connect”,在端口那輸入” \\.\pipe\com_1”下面默認,確定
提示
暈,怎麼回事?用windbg就可以啦.打開源碼看看,(有源代碼就是好,^_^);這個程序的代碼很少.
看到這,就知道怎麼回事了(注意這段在D:\ReactOS\ReactOS_src\boot\freeldr\fdebug\rs232.c文件中):
代碼:
_stprintf(PortName, TEXT("\\\\.\\%s"), CommPort);
hPortHandle = CreateFile(PortName,
GENERIC_READ|GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
0,
0);
馬上將port名改成pipe\com_1,可是又出錯了:
接著看代碼,這裡(在同目錄下的fDebug.c中):
代碼:
_stprintf(String, TEXT("%s,n,8,1"), strBaudRate);
if (!Rs232ConfigurePortWin32(String))
{
MessageBox(hMainWnd, TEXT("Error configuring port!"), TEXT("Error"), MB_OK|MB_ICONSTOP);
bConnected = FALSE;
return;
}
接著看看這個函數Rs232ConfigurePortWin32(同目錄下的rs232.c中):
代碼:
BOOL Rs232ConfigurePortWin32(TCHAR* DeviceControlString)
{
DCB dcb;
DWORD ErrorCode;
memset(&dcb, 0, sizeof(DCB));
dcb.DCBlength = sizeof(dcb);
if (!BuildCommDCB(DeviceControlString, &dcb))
{
ErrorCode = GetLastError();
_tprintf(TEXT("BuildCommDCB() failed. GetLastError() = %lu.\n"), ErrorCode);
return FALSE;
}
if (!SetCommState(hPortHandle, &dcb))
{
ErrorCode = GetLastError();
_tprintf(TEXT("SetCommState() failed. GetLastError() = %lu.\n"), ErrorCode);
return FALSE;
}
// Set the timeouts
if (!Rs232SetCommunicationTimeoutsWin32(MAXDWORD, 0, 0, 0, 0))
{
return FALSE;
}
return TRUE;
}
查了下msdn沒多大用,(有興趣的自己看),去掉.將fDebug.c中的那段去掉.
這裡也說下:這個程序的作者也真夠馬虎的點”connect”出錯後,也不知道將disConnect變為禁用將connect變為可用,害的我每次都得重新運行下程序,我們改過來:
在連接失敗的地方加上
代碼:
EnableFileMenuItemByID(IDM_FILE_DISCONNECT, FALSE);
EnableFileMenuItemByID(IDM_FILE_CONNECT, TRUE);
就行了
趕緊試了下….成功了:
如下:
呵呵.接著去他老家的論壇看了看Kernel_Debug的用法,wiki上都有我就不多說了.
在這裡: http://www.reactos.org/wiki/index.php/Kdbg
對了這裡按Tab + K 鍵中斷進行調試,和softice似的,輸命令的時候必須將窗口切入到ReactOS中再輸入,雖然不是在fDebug中輸入的加上鼠標什麼的都不管事但是ReactOS會將命令通過串口傳過來.
我們試試查看寄存器:
輸入:regs
顯示如圖:
注意:調試必須是內核帶調試的版本,怎麼編譯調試版本,WIKI上都說了,大家可以參考
結束語:這裡僅僅是指名了個方向,具體還要大家慢慢的研究,探索…..
老鳥飛過
也不知道是放在編程這塊呀,還是放在調試那塊,想了下編程這塊常來放在這吧
附上改過後的fDebug
2011年9月6日星期二
ODbgScript源碼學習(十八)
int setProgLineResult(int line, DWORD result) //
{
char buf[17];
sprintf(buf, "%X", result); //打印
string str(buf);
return setProgLineResult(line, str); //使用字符串設置行
}
int setProgLineResultFloat(int line, long double result) {
char buf[128];
sprintf(buf, "%lf", result);
string str(buf);
while (true)
{
if (str.length() <= 3) break; //如果長度小於等於3,中斷
if (str[str.length()-1] == '0') //如果最後一個字符為0
str.erase(str.length()-1,1); //清除
else
break; //中斷
}
return setProgLineResult(line, str); //設置行
}
int setProgLineResult(int line, string& result) //設置行返回值
{
if (line>ollylang->script.size()) return 0; //參數大於腳本大小,返回0
char values[PROG_VAL_LEN];
t_wndprog_data *ppl;
ppl = (t_wndprog_data *) Getsortedbyselection(&(ollylang->wndProg.data),line); //獲取分類數據
if (ppl->type & PROG_TYPE_LABEL) //類型為標籤,返回失敗
return false;
strncpy(ppl->result,CleanString(result).c_str(),PROG_RES_LEN);
if (strcmp(ppl->values,""))
{
if (ppl->values[0] != ',')
{
strcpy(values,ppl->values);
strncpy(&ppl->values[1],values,PROG_VAL_LEN-2);
ppl->values[0]=',';
}
}
return true;
}
void clearProgLines()
{
ollylang->pgr_scriptpos=0;
if (!ollylang->tProgLines.empty()) //如果行不為空
{
Deletesorteddatarange(&(ollylang->wndProg.data),0,0xffffffff); //傷處分類數據域
ollylang->tProgLines.clear(); //清除行
InvalidateProgWindow();
}
}
void resetProgLines()
{
vector<t_wndprog_data>::iterator iter=ollylang->tProgLines.begin(); //使用容器vector 定義一個開始
int line=0;
t_wndprog_data *ppl;
while (iter!=ollylang->tProgLines.end()) //黨不等於結束時
{
ppl = (t_wndprog_data *) Getsortedbyselection(&(ollylang->wndProg.data),line); //獲取分類數據
//reset executed color
if ((ppl->type & PROG_TYPE_COMMAND)) //忽略標籤和註釋ignore labels/comments
ppl->type &= PROG_TYPE_COMMAND;
strcpy(ppl->result,"");
strcpy(ppl->values,"");
//ppl->jumpto = 0;
ppl->eip = 0;
line++;
iter++;
}
InvalidateProgWindow();
}
int getProgLineType(int line) //獲取行類型
{
t_wndprog_data *ppl;
ppl = (t_wndprog_data *) Getsortedbyselection(&(ollylang->wndProg.data),line);
if (ppl==NULL)
return false;
return (ppl->type & PROG_TYPE);
}
int setProgLineAttr(int line,int type)
{
t_wndprog_data *ppl;
ppl = (t_wndprog_data *) Getsortedbyselection(&(ollylang->wndProg.data),line);
if (ppl==NULL)
return false;
ppl->type &= PROG_TYPE;
ppl->type |= type;
return true;
}
int isProgLineComment(int line)
{
t_wndprog_data *ppl;
ppl = (t_wndprog_data *) Getsortedbyselection(&(ollylang->wndProg.data),line);
if (ppl==NULL)
return false;
if (ppl->type & PROG_TYPE_COMMENT)
{
return true;
}
return false;
}
int isProgLineBP(int line)
{
t_wndprog_data *ppl;
ppl = (t_wndprog_data *) Getsortedbyselection(&(ollylang->wndProg.data),line);
if (ppl==NULL)
return false;
if (ppl->pause && ollylang->wndProg.hw)
{
focusonstop=4;
}
return ppl->pause;
}
标签:
源代碼,
ODbgScript,
ODbgScript源碼學習,
OllyDbg
订阅:
博文 (Atom)