2011年8月31日星期三

ODbgScript源碼學習(十)

char * HexString2BinArray(const char * s) //轉換Hex字符串到bin數組
{
char HexBuf[3];
char * result=new char[(strlen(s) /2)+1]; //定義一個長度為s一半+1的char指針
result[0]=0;//

int i=0;
while (strlen(s)) //設置長度的不為空
{
strncpy(HexBuf,s,2); //字串複製
HexBuf[2]=0;
result[i]=(char)strtoul(HexBuf,0,16); //返回變量的i為為轉換后的hexbuf
i++;
s+=2; //s+2
}
i++;

return result; //返回結果
}

char WildSymbolToChar(const char* x) //Wild符號轉換成char
{
char n;

if (x[0]=='?') //如果x[0]為'?'
n=x[1]; //n為?的第二位
else
n=x[0]; //否則就為第一位

if (n>='0' && n<='9') //如果n為數字
n-='0'; //
else
{
if (n>='a' && n<='f') //如果n為小寫字幕字母
n-='a';
else
{
if (n>='A' && n<='F') //如果n為大寫字母
n-='A';
}
}
if (x[1]=='?') //如果x[1]為?
n=n<<4;

return n;
}

2011年8月30日星期二

ODbgScript源碼學習(九)

Search.h:

#pragma once

bool Replace(char * s,const char * searchstr,const char * replstring,size_t length);
//bool CompareChar(const char src, char* cmp); //替換函數
int FindWithWildcards(const char* source, const char* findstring, size_t len);
//char * Byte2Hex(char b); //尋找寬通配符

Search.cpp:

#include "StdAfx.h"
#include <math.h>

bool CompareChar(const char src, char* cmp)//比較char
{
if(strstr(cmp, "??")) // ??查找是否有"??"
return true;

if(strstr(cmp, "?") == cmp) // ?6是否有
{
char low = src % 0x10;//源字串%0x10
char val = (char)strtoul(cmp + 1, 0, 16);//轉換為16進制
if(val == low)//如果與前面顯得
return true;//返回真
return false;
}
else if(strstr(cmp, "?") == cmp + 1) // 5?如果"?"在cmp+1的位置
{
cmp[1] = 0;//第二位為0
char high = (src - src % 0x10) / 0x10;//高位計算結果
char val = (char)strtoul(cmp, 0, 16);//轉換16進制
if(val == high)//如果等於高位
return true;//為真
return false;
}
else // 56
{
char high = (src - src % 0x10) / 0x10;//其他高位計算
char low = src % 0x10;//低位計算
char val2 = (char)strtoul(cmp + 1, 0, 16);//轉換為16進制
cmp[1] = 0;//第二位為0
char val1 = (char)strtoul(cmp, 0, 16);//16進制轉換
if(high == val1 && low == val2)//如果高位和低位等於轉換結果
return true; //返回真
return false;
}
}

int FindWithWildcards(const char* source, const char* findstring, size_t len)
{
char cmp[3] = {0};  //第三位為{0}
int findlen = ceil(((double)strlen(findstring) / 2));//尋找長度為向上捨入字串findstring長度的一半
if(len < findlen)//如果輸入長度小於字串findstring長度
return -1;//返回-1

for(int i = 0; i < len; i++)  //len長度內循環
{
for(int j = 0; j < findlen; j++)//findlen長度內循環
{
strncpy(cmp, findstring + j * 2, 2);  //複製2個字節的cmp
if(!CompareChar(source[i+j], cmp))//比較字串
break;
else if(j == (findlen - 1))//如果尋找長度為循環次數
return i;//返回i
}
}
return -1;
}



2011年8月28日星期日

ODbgScript源碼學習(八)

guicon.h
#pragma once

#ifdef _DEBUG
#ifndef __GUICON_H__

#define __GUICON_H__



//#include "stdafx.h"

void RedirectIOToConsole(); //重定向輸出輸入到命令行

#endif

#endif

/* End of File */

guicon.cpp:

#ifdef _DEBUG //如果定義調試選項

#include "StdAfx.h" //包含頭文件"StdAfx.h"

#ifndef _USE_OLD_IOSTREAMS
using namespace std;
#endif

// maximum mumber of lines the output console should have
const WORD MAX_CONSOLE_LINES = 500; //最多能輸出命令行數

void RedirectIOToConsole()
{
int hConHandle; //命令行句柄
long lStdHandle; //std句柄
CONSOLE_SCREEN_BUFFER_INFO coninfo; //命令行緩衝區信息
FILE *fp; //文件指針

// allocate a console for this app
AllocConsole(); //分配一個命令行

// set the screen buffer to be big enough to let us scroll text
GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE),
&coninfo); //獲取命令行屏幕緩衝區信息
coninfo.dwSize.Y = MAX_CONSOLE_LINES; //大小的y為500
SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE),
coninfo.dwSize); //獲取std輸出句柄后設置控制台屏幕緩衝區大小

//重定向無緩衝區STD輸出命令行 redirect unbuffered STDOUT to the console
lStdHandle = (long)GetStdHandle(STD_OUTPUT_HANDLE); //獲取std句柄
hConHandle = _open_osfhandle(lStdHandle, _O_TEXT); //打開osf句柄
fp = _fdopen( hConHandle, "w" ); //打開
*stdout = *fp;
setvbuf( stdout, NULL, _IONBF, 0 ); //把緩衝區與流相關

// redirect unbuffered STDIN to the console
lStdHandle = (long)GetStdHandle(STD_INPUT_HANDLE);
hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
fp = _fdopen( hConHandle, "r" );
*stdin = *fp;
setvbuf( stdin, NULL, _IONBF, 0 );

// redirect unbuffered STDERR to the console
lStdHandle = (long)GetStdHandle(STD_ERROR_HANDLE);
hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
fp = _fdopen( hConHandle, "w" );
*stderr = *fp;
setvbuf( stderr, NULL, _IONBF, 0 );

// 使用 cout, wcout, cin, wcin, wcerr, cerr, wclog and clog
// point to console as well
ios::sync_with_stdio(); //設置c++ 的 iostream 和 c 的 stdio同步
}
#endif
//End of File


2011年8月27日星期六

ODbgScript源碼學習(七)

//在反彙編窗口上下文菜單下調用
int mruGetCurrentMenu(char* buf) {

char buf2[4096] = {0}; //定義為0,4096個字節的緩衝區buf2
char key[5];
int p=0;
int c,v;
string path;

HINSTANCE h=hinstModule(); //獲取它自身的模塊句柄
strcpy(key,"MRU "); //key為"mru"

for(int n=1; n<=5; n++) {
key[3]=n+0x30; //ASCII n

ZeroMemory(&buf2, sizeof(buf2));
Pluginreadstringfromini(h,key,buf2,0);
if (strlen(buf2)) {
if (PathFileExists(buf2)) {
buf[p]=0x32; p++;
buf[p]=key[3]; p++;
buf[p]=0x20; p++;
path=buf2;
c=path.rfind('\\') + 1;

while ( (v = strchr(&buf2[c],',')-&buf2[c]) > 0) {
buf2[c+v]='.';
}
while ( (v = strchr(&buf2[c],'{')-&buf2[c]) > 0) {
buf2[c+v]='[';
}
while ( (v = strchr(&buf2[c],'}')-&buf2[c]) > 0) {
buf2[c+v]=']';
}

strcpy(&buf[p],&buf2[c]); p+=strlen(&buf2[c]);
buf[p]=',';p++;
}
}
}
if (p>0) buf[--p]=0;

return p;

}

int mruGetCurrentMenu(HMENU mmru,int cmdIndex) {

char buf2[4096] = {0};
char key[5];
int c,v;
string path;

HINSTANCE h=hinstModule();
strcpy(key,"MRU ");

for(int n=1; n<=5; n++) {
key[3]=n+0x30; //ASCII n

ZeroMemory(&buf2, sizeof(buf2));
Pluginreadstringfromini(h,key,buf2,0);
if (strlen(buf2)) {
if (PathFileExists(buf2)) {
path=buf2;
c=path.rfind('\\') + 1;
AppendMenu(mmru,MF_STRING,cmdIndex+n,&buf2[c]); //應用菜單
}
}
}

return 1;
}


int mruCmdMenu(HMENU mmru,int cmdIndex) {

AppendMenu(mmru,MF_STRING,cmdIndex+1,"ESP定律");
return 1;
}




//MessageBox(hwmain,buf,"",MB_OK|MB_ICONEXCLAMATION|MB_TOPMOST);

ODbgScript源碼學習(六)

接下來繼續
mru.h:
void mruAddFile(char* szFilePath); //添加文件
int mruGetMenu(char* buf); //獲取菜單
int mruGetCurrentMenu(char* buf); //獲取當前菜單
int mruGetCurrentMenu(HMENU mmru, int cmdIndex); // 獲取腳本上下文菜單 For Dynamic MRU List (Script Window Context Menu)
int mruCmdMenu(HMENU mmru,int cmdindex); //cmd菜單

mru.cpp:
//mru使用的原因是Ollydbg主菜單是靜態的,所以為下一個olldbg開始存儲mru

void mruAddFile(char* szFilePath) { //參數是文件路徑
char buf[4096] = {0}; //定義一個字節為0大小為4096的緩衝區

int n;
char key[5]; //定義字串
strcpy(key,"MRU "); //把"MRU"特徵字串複製到key

HINSTANCE h=hinstModule(); //獲取自身ODbgScript.dll的模塊句柄

for(n=1; n<=5; n++) { //n為1至5時循環
key[3]=n + 0x30; //ASCII n 根據n不同 key為"MRU1""MRU2""MRU3""MRU4""MRU5"
ZeroMemory(&buf, sizeof(buf)); //buf歸0
Pluginreadstringfromini(h,key,buf,0); //讀ollydbg.ini文件中的MRU存取的路徑到buf
if (strcmp(buf,szFilePath)==0) { //如果文件路徑與參數輸入的路徑相同
//Move File to first MRU移動文件到最先的MRU
key[3]='1'; //即"MRU1"
Pluginreadstringfromini(h,key,buf,0); //再次讀ollydbg.ini第一項"MRU1"
Pluginwritestringtoini(h,key,szFilePath); //寫入新路徑
key[3]=n + 0x30; //重新寫入當前MRU讀到的位置
Pluginwritestringtoini(h,key,buf); //寫入當前位置的MRU
return;
}
}
for(n=4; n>0; n--) { //如果n從4遞減到1
//Add File then Move others 添加文件然後移除其他
key[3]=n+0x30; //根據n不同 key為"MRU4""MRU3""MRU2""MRU1"
ZeroMemory(&buf, sizeof(buf)); //緩衝區歸0
Pluginreadstringfromini(h,key,buf,0); //讀出路徑到buf
if (strlen(buf)) { //如果路徑不為空
key[3]=n+1+0x30; //移到下一位MRU
Pluginwritestringtoini(h,key,buf); //即把路徑往下移
}
}
key[3]='1'; //MRU1
Pluginwritestringtoini(h, key, szFilePath); //寫入路徑

}

//在主菜單被調用一次ON MAIN MENU, ITS CALLED ONCE

int mruGetMenu(char* buf) {

char buf2[4096] = {0}; //定義為0長度為4096的緩衝區
char key[5];
char key2[5];
int p=0;
int c,v;
string path; //路徑

HINSTANCE h=hinstModule(); //獲取自身ODbgScript.dll的模塊句柄
strcpy(key,"MRU "); //賦值"MRU"到key
strcpy(key2,"MRU "); //賦值"MRU"到key2

for(int n=1; n<=5; n++) { //n為1至5時循環
key[3]=n+0x30; //ASCII n 根據n不同 key3"1""2""3""4""5"
key2[3]=key[3]; //複製一個副本到key2

ZeroMemory(&buf2, sizeof(buf2)); //緩衝區歸0
Pluginreadstringfromini(h,key,buf2,0); //獲取ini文件中的MRU到buf2
Pluginwritestringtoini(h,key2, buf2); //寫入buf2到mru
if (strlen(buf2)) { //如果路徑不為空
if (PathFileExists(buf2)) { //如果路徑有效
buf[p]=0x32; p++; //緩衝區的第p為"2"
buf[p]=key[3]; p++; //緩衝區的第p+1為"3"
buf[p]=0x20; p++; //緩衝區的第p+2為" "
path=buf2; //路徑為讀出的路徑
c=path.rfind('\\') + 1; //使用std字串函數最後一次"\\"的位置,并到下一位

while ( (v = strchr(&buf2[c],',')-&buf2[c]) > 0) { //"\\"之後一位開始查找第一個','位置,v是最後一個"\\"和之後第一個','的距離,假如','存在而且兩點距離不重合時候
buf2[c+v]='.'; //替換','到'.'
}
while ( (v = strchr(&buf2[c],'{')-&buf2[c]) > 0) { //"\\"之後一位開始查找第一個'{'位置,v是最後一個"\\"和之後第一個'{'的距離,假如','存在而且兩點距離不重合時候
buf2[c+v]='['; //替換','到'['
}
while ( (v = strchr(&buf2[c],'}')-&buf2[c]) > 0) { //"\\"之後一位開始查找第一個'}'位置,v是最後一個"\\"和之後第一個'}'的距離,假如','存在而且兩點距離不重合時候
buf2[c+v]=']'; //替換','到']'
}

strcpy(&buf[p],&buf2[c]); p+=strlen(&buf2[c]);//串拷貝
buf[p]=',';p++;
}
}
}
if (p>0) buf[--p]=0; //如果p大於0,緩衝區buf的前p為歸0

return p; //返回指針
}



2011年8月25日星期四

ODbgScript源碼學習(五)

int var::compare(const var& rhs) const //比較函數
{
// less than zero this < rhs
// zero this == rhs
// greater than zero this > rhs
if(vt != rhs.vt || vt == EMP || rhs.vt == EMP) //如果關鍵字var不為vt,或者vt為emp或者rhs.vt為emp
return -2; //則返回-2
if(vt == DW) //如果var的類型為雙字節類型 { if(dw < rhs.dw) return -1; //如果dw小於rhs.dw,則返回-1 if(dw == rhs.dw) return 0; //如果dw等於rhs.dw,則返回0 if(dw > rhs.dw) return 1; //如果dw大於rhs.dw,則返回1 } else if(vt == FLT) //如果var的類型為flt { if(flt < rhs.flt) return -1; //如果flt小於rhs.flt,則返回-1 if(flt == rhs.flt) return 0; //如果flt等於rhs.flt,則返回0 if(flt > rhs.flt) return 1; //如果flt大於rhs.flt,則返回1 } else if(vt == STR) { //如果var的類型為字符串類型 if (isbuf == rhs.isbuf) //如果使用的是否使用緩衝區與rhs一致 return str.compare(rhs.str); //返回字符串比較 else { //不一致的話 string Hex; //定義字符串 if (isbuf) { //如果使用緩衝區 //Buffer / String string s=str; //定義變量s為字符串str UnquoteString(s,'#','#'); //查找結束符 Str2Hex((string)rhs.str,Hex,rhs.size); //轉換rhs.str到hex類型,存入hex return s.compare(Hex); //返回s比較hex } else { //如果未使用緩衝區 //String / Buffer string s=rhs.str; //定義變量s為字符串rhs.str UnquoteString(s,'#','#'); //轉換rhs.str到hex類型,存入hex Str2Hex((string)str,Hex,size); //轉換str到hex類型,存入hex return Hex.compare(s); //返回hex比較s } } } return 0; //返回0
}

int var::compare(const string& rhs) const //比較字串類型
{
var tmp; //定義var的實例tmp
tmp.vt = STR; //tmp的vt為字符串類型
tmp.str = rhs; //tmp的str為rhs
return compare(tmp);
}

int var::compare(const ulong& rhs) const //比較ulong類型
{
var tmp(rhs); //定義var的實例tmp長度為rhs
return compare(tmp); //比較
}

int var::compare(const int& rhs) const //比較int類型
{
var tmp(rhs); //定義var的實例tmp長度為rhs
return compare(tmp); //返回比較
}

int var::compare(const long double& rhs) const //比較int類型
{
var tmp(rhs); //定義var的實例tmp長度為rhs
return compare(tmp); //返回比較
}

string var::strclean(void) //字符串清除
{
return CleanString(strbuff()); //使用字符串函數CleaString清除字符串緩衝區
}

string var::strbuffhex(void) //截去頭尾的
{
if (isbuf) //如果使用緩衝區,截去頭尾
//#001122# to "001122"
return str.substr(1,str.length()-2);
else { //如果未使用緩衝區
string s;
Str2Hex(str,s,size); //軟化str到HEX類型
return s; //返回hex
}
}

string var::strbuff(void) //字符串緩衝區
{
if (isbuf) { //如果使用緩衝區
//#303132# to "012"
string s=strbuffhex(); //字符串緩衝區到hex轉換
string tmp=s.substr(0,size); //去字符串開頭到size得大小
Str2Rgch(s,(char*)tmp.c_str(),size); //轉換字符串到rgch
s=tmp; //結果賦值給s
return s; //函數返回運算結果
} else
return str; //否則直接返回str
}

void var::resize(ulong newsize) //重設大小
{
if (vt==DW){ //如果var的類型為雙字節類型
if (newsize==1) { //如果新大小為1
dw&=0xFF; // 位与赋值為0xFF
}
else if (newsize==2) { //如果大小為2
dw&=0xFFFF; // 位与赋值為0xFFFF
}
}
if (size > newsize) { //如果大小大於重設大小 if (isbuf) { //如果使用緩衝區 *this = "#"+strbuff().substr(0,newsize)+"#"; //開頭結尾為"#"中間為指針為字符串緩衝區的0位開始,大小為newsize的子字符串
} else { //如果未使用緩衝區 *this = strbuff().substr(0,newsize); //指針為字符串緩衝區的0位開始,大小為newsize的子字符串 } } } }

2011年8月24日星期三

ODbgScript源碼學習(四)

var& var::operator+=(const var& rhs) //重載+=,根據關鍵字類型vt來把rhs的類型賦給+=運算對象,返回自身指針
{
if(rhs.vt == DW) //如果是雙字節類型
*this+=rhs.dw; //自身指針+=運算為rhs.dw
else if(rhs.vt == FLT) //如果是FLT類型
*this+=rhs.flt; //自身指針+=運算為rhs.flt
else if(rhs.vt == STR) { //如果是字符串類型
//operator+=(const string& rhs) //操作符重載為字串類型
*this+=rhs.str; //自身指針+=運算為rhs.str
}
return *this;
}

var& var::operator+=(const string& rhs) //重載操作符,字符串類型賦值給對象,返回自身指針
{
string s; //定義字符串變量s
if(vt == STR) { //如果關鍵字var類型為STR
string s=rhs; //定義變量為rhs
if (UnquoteString(s,'#','#')) { //如果字符串未曾結束
if (!isbuf) { //如果沒有使用緩衝區,即緩衝區標誌為假
//String + buf Hex Buffer to String ok
size_t len=s.length()/2; //定義size_t類型長度為字串長度的一半
char* buf = (char*)malloc(len+1); //分配長度為字串長度一半加1長度的緩衝區
Str2Rgch(s,buf,len+1); //字串s轉換到Rgch類型,轉換目的緩衝區為前面分配的緩衝區,長度為字串長度的一半加1
s.assign(buf,len); //字串賦值緩衝區長度為len
str += s; //類的全局變量+=為s,str為str+s
size += len; //size為size+len
free(buf); //釋放緩衝區
} else { //如果已經使用緩衝區
// Buffer + Buffer
str = "#"+str.substr(1,str.length()-2)+s+"#"; //替換字串str開頭結尾為"#",在結束"#"前插入字串s
size += s.length()/2; //大小為原本大小加上s長度的一半
}
} else { //如果字符串已經結束
if (!isbuf) { //未使用緩衝區
//str + str
str += rhs; //全局字符串變量str為原str加上rhs
size += rhs.length(); //大小為原來大小加上rhs長度
} else { //如果使用緩衝區
//buf + str
string Hex; //定義字串hex
Str2Hex(s,Hex,s.length()); //s轉換類型到hex類型
str = "#"+str.substr(1,str.length()-2)+Hex+"#"; //截掉str開頭結尾字符,加上轉換后字串,新字串開頭結尾為"#"
size += s.length(); //大小為原大小加上字符串長度
}
}

} else if(vt == DW) { //如果關鍵字var是雙字節類型
var v=(string)rhs; //用這個var類定義變量v為字符產類型的rhs

char dwbuf[12]; //定義12個字節的char類型變量dwbuf
if (v.isbuf) { //類v的使用緩衝區標誌為真的話,即使用緩衝區
//ulong + BUFFER >> CONCATE HEX
s = strbuffhex(); //用函數strbuffhex截取掉開頭和結尾的"#"
sprintf(dwbuf, "%08X",dw); //打印到緩衝區
*this = "#"+((string)dwbuf)+s+"#"; /截掉dwbuf開頭結尾字符,加上新字串s,新字串開頭結尾為"#"
} else { //如果未曾使用緩衝區
//ulong + STRING >> CONCATE ultoa+str
s = strupr(ultoa(dw, dwbuf, 16)); //先把dwbuf從無符號長整型轉換為字符串,再把它轉換為大寫
*this = s+v.str; //自身指針為s加上類v的str全局變量
}
}

return *this; //返回自身指針
}

var& var::operator+=(const ulong& rhs) //重載操作符+=,ulong賦值給對象
{
if(vt == DW) //如果關鍵字類型為雙字節
dw += rhs; //dw為dw+rhs
else if(vt == FLT) //如果關鍵字類型為FLT
flt += rhs; //dw為flt+rhs
else if(vt == STR) { //如果關鍵字類型為字符串
string s;
char dwbuf[12]; //定義長度為12字節的char變量dwbuf
if (isbuf) { //如果使用了緩衝區
//Concate Num ulong to a buffer (4 octets)
s = strbuffhex(); //截去開頭結尾的"#"
sprintf(dwbuf, "%08X",rev(rhs)); //格式化輸出已反向雙字節的rhs
*this = "#"+s+dwbuf+"#"; //自身指針為字串s加上dwbuf,開頭結尾加上"#"
} else { //如果未使用緩衝區
//Add Number to a String添加數字到字符串
s = strupr(ultoa(rhs, dwbuf, 16)); //把無符號類型dwbuf轉換為16字節的字符串,再轉換我大寫
str += s; //str為str加上新的s
size += s.length(); //大小我s的長度
}
}
return *this; //返回自身指針
}

var& var::operator+=(const int& rhs) //重載操作符+=,int賦值給對象
{
if(vt == DW) //如果關鍵字var的類型為雙字節
dw += (ulong)rhs; //dw為dw加上轉換類型後的rhs
else if(vt == FLT) //如果關鍵字var的類型為FLT
flt += rhs; //flt為dw加上rhs
else if(vt == STR) //如果關鍵字var的類型為字符串
*this+=(ulong) rhs; //自身指針為自身指針加上轉換類型後的rhs

return *this; //返回自身指針
}

var& var::operator+=(const long double& rhs) //重載操作符+=,long double賦值給變量
{
if(vt == FLT) //如果vt類型我FLT
flt += (long double)rhs; //flt為flt加上轉換類型後的rhs
return *this; //返回自身指針
}


2011年8月23日星期二

ODbgScript源碼學習(三)

var::var(ulong rhs) //
{
vt = DW; //變量類型為雙字節
dw = rhs; //雙字節被賦予為未知長整型
flt = 0;
str = "";
size = sizeof(rhs); //大小為rhs大小
isbuf = false;
}

var::var(int rhs)
{
vt = DW; //int類型是變量var類型為vt
dw = (ulong)rhs; //dw為rhs類型轉換
flt = 0;
str = "";
size = sizeof(rhs);
isbuf = false;
}

var::var(long double rhs)
{
vt = FLT; //雙精度類型
flt = rhs; //
dw = 0;
str = "";
size = sizeof(rhs);
isbuf = false;
}


var& var::operator=(const var& rhs) //重載賦值號=,對象間賦值,返回自身指針
{
vt = rhs.vt;
dw = rhs.dw;
str = rhs.str;
flt = rhs.flt;
size = rhs.size;
isbuf = rhs.isbuf;
return *this;
}

var& var::operator=(const string& rhs) //重載賦值號=,字串類型賦值給對象,返回自身指針
{
vt = STR;
dw = 0;
flt = 0;
str = rhs; //str為字符串
string s=rhs;
if (UnquoteString(s,'#','#')) { //判斷字串是否結束
size = s.length()/2; //初始大小為字符串長度一半
int (*pf)(int) = toupper; //轉換字符串大小寫
transform(str.begin(), str.end(), str.begin(), pf); //遍歷容器str,從str.begin()開始,到str.end()結束,str.begin()寫入目標地址,執行pf轉換字符串大小寫操作
isbuf = true; //使用了緩衝區
} else {
size = rhs.length(); //如果結束,大小為字符串的一半
isbuf = false; //未曾使用緩衝區
}
return *this; //返回自己的指針
}

var& var::operator=(const ulong& rhs) //重載操作符=,ulong賦值給對象,返回自身指針
{
vt = DW;
dw = rhs;
flt = 0;
str = "";
size = sizeof(rhs);
isbuf = false;
return *this;
}

var& var::operator=(const int& rhs) //重載操作符=,int複製給對象,返回自身指針
{
vt = DW;
dw = (ulong)rhs;
flt = 0;
str = "";
size = sizeof(rhs);
isbuf = false;
return *this;
}

var& var::operator=(unsigned short& rhs) //重載操作符=,short賦值給對象,返回自身指針
{
vt = DW;
dw = rhs;
flt = 0;
str = "";
size = sizeof(rhs);
isbuf = false;
return *this;
}

var& var::operator=(unsigned char& rhs) //重載操作符,char賦值給對象,返回自身指針
{
vt = DW;
dw = rhs;
flt = 0;
str = "";
size = sizeof(rhs);
isbuf = false;
return *this;
}

var& var::operator=(const long double& rhs) //重載操作符,long double賦值給對象,返回自身指針
{
vt = FLT;
dw = 0;
flt = (long double)rhs;
str = "";
size = sizeof(rhs);
isbuf = false;
return *this;
}


ODbgScript源碼學習(二)

var.h的代碼

#pragma once //避免頭文件被多次定義

using namespace std; //使用std命名空間

enum vtype { EMP, DW, STR, FLT }; //定義枚舉變量類型vtype

typedef unsigned long ulong; //定義類型ulong

class var //var類
{
public:
ulong dw;
string str;
long double flt;
vtype vt; //var關鍵字定義的變量的類型
bool isbuf; //緩衝區標誌
int size; //大小

//使用函數重載定義關鍵字var跟著不同類型
var();
var(const var& rhs);
var(string& rhs);
var(ulong rhs);
var(int rhs);
var(long double rhs);

// less than zero this < rhs
// zero this == rhs
// greater than zero this > rhs
int compare(const var& rhs) const;
int compare(const string& rhs) const;
int compare(const ulong& rhs) const;
int compare(const int& rhs) const;
int compare(const long double& rhs) const;

string strclean(void); //字符串清除
string strbuffhex(void); //字符串緩衝區hex
string strbuff(void); //字符串緩衝區

//var的參數重載,使得參數為不同類型
var& operator=(const var& rhs);
var& operator=(const string& rhs);
var& operator=(const ulong& rhs);
var& operator=(const int& rhs);
var& operator=(unsigned short& rhs);
var& operator=(unsigned char& rhs);
var& operator=(const long double& rhs);

//var的參數重載,使得參數為不同類型
var& operator+=(const var& rhs);
var& operator+=(const string& rhs);
var& operator+=(const ulong& rhs);
var& operator+=(const int& rhs);
var& operator+=(const long double& rhs);

void resize(ulong newsize); //重設大小

};

var.cpp代碼

#include "StdAfx.h"
#include "var.h"

var::var()
{
vt = EMP; //枚舉變量vt賦值為枚舉變量中的EMP
dw = 0; //dw初始值為0
flt = 0; //雙精度長整型flt初始值為0
str = ""; //字符串為空
size = 0; //大小初始值為0
isbuf = false; //isbuf初始值為false
}

var::var(const var& rhs) //參數類型rhs為var類的地址
{
vt = rhs.vt; //把rhs的vt賦值給vt
dw = rhs.dw;
flt = rhs.flt;
str = rhs.str;
size = rhs.size;
isbuf = rhs.isbuf;
}

var::var(string& rhs) //rhs為字符串的&
{
vt = STR; //腳本中,var關鍵字后定義變量類型為STR
dw = 0;
flt = 0;
str = rhs; //字符串初始變量為參數rhs,即腳本中var變量后的字符串
string s=rhs;
if (UnquoteString(s,'#','#')) { //使用幫助函數(HelperFunctions中)結束字符串,如果S未曾結束
size = s.length()/2; //大小為字符串s長度的一半
int (*pf)(int) = toupper; //轉換大小寫
transform(str.begin(), str.end(), str.begin(), pf); //遍歷容器元素,起始為str.begin(),結束為str.end(),str.begin()寫入目標起始地址,執行pf操作
isbuf = true; //緩衝區使用為真
} else {
size = rhs.length(); //否則大小為rhs.length()
isbuf = false; //緩衝區使用為假
}
}


2011年8月22日星期一

ODbgScript源碼學習(一)

ODbgScript是一款非常重要的OD插件,雖然現在還沒有支持新版OD,它的源碼卻是學習OD編程一個好的範例,今天開始,閱讀它的源碼學習.

我查看的是ODbgScript 1.63版,這個源碼由這幾個文件構成:
var.h和var.cpp 定義腳本的關鍵字var和其相關
mru.h和mru.cpp 菜單相關
guicon.h和guicon.cpp 輸入輸出重定向到命令行
seach.h和seach.cpp 數據類型轉換相關
progress.h和progress.cpp 腳本行與腳本數據表相關
LogWindows.h和LogWindows 記錄窗口相關
HelperFunctions.h和HelperFunctions.cpp 搜索與類型轉換相關
OllyLang.h和OllyLang.cpp 腳本提供的功能相關與腳本容器相關
OllyLangCommands.cpp 腳本語言各命令關鍵字具體內容
ODbgScript.cpp 腳本輸出接口

2011年8月21日星期日

VProtect 調試記錄

近段時間調試了VProtect 2.06,基本上該找的都找到了,就是修復難,正好看見Unpack論壇有人發出一些訊息,如此我也把我的調試記錄發出來了.

VProtect 2.06的OEP查找不用那麼困難,只要一個函數GetSystemTimeAsFileTime,就行了
Found intermodular calls, item 510
Address=010070F1
Disassembly=CALL DWORD PTR DS:[<&KERNEL32.GetSystemTimeAsFileTime>]
Destination=kernel32.GetSystemTimeAsFileTime
010070F1 E8 B9570500 CALL NOTEPAD_.0105C8AF

之後再在code段下內存訪問斷點,執行幾下就到OEP了,

這個殼難度不是在找OEP,而是修復輸出表,他是把代碼放在一個動態分配的內存段中,其中有一個地方

010296F0 FF15 5C800101 CALL DWORD PTR DS:[<&KERNEL32.GetProcAddress>] ; kernel32.GetProcAddress

這個殼找OEP是不難滴,硬件HOOK是浮雲,修復IAT和暗樁才是重點

2011年8月20日星期六

Ollydbg 2.01 alpha 4 試用報告(四):選項設置(5)


Ollydbg 2.01當中分析選項沒有什麽變化,自己設置一下就可以了.

我們看看新增加的目錄選項,在0llydbg 1.01當中,目錄選項是在界面選項窗口的,現在它吧界面選項和調試選項一起合並為選項

如圖:

你可以設置你的udd文件目錄的路徑和插件文件夾路徑,這裡還多出了一項,設置你的API幫助文件的路徑

設置之後再Ollydbg 2.01 中非常有用,在一個API函數地址的地方右鍵會出現一個菜單選項(Help on API function)

如圖



選擇之後,你就可以在Win32.hep中非常容易的看到它的函數信息了

到這裡Ollydbg 2.01 alpha 4 試用報告系列文章告一段落了,如果你還想繼續瞭解Ollydbg的情況,請繼續關注我的部落格

http://0mblogger.blogspot.com/ 主部落格
http://0mblogger.blog.com/ 鏡像一
http://lypwell.pixnet.net/blog 鏡像二

2011年8月19日星期五

Ollydbg 2.01 alpha 4 試用報告(四):選項設置(4)

Ollydbg 2.01 調試選項相對于Ollydbg 1.01版也多了很多,這些改變給我們多了許多選擇的餘地,先看一下Debugging Options,這裡面最大的特色是單步中斷我們可以使用硬件斷點和運行相關的操作函數的選擇,

看圖
一般情況下,單步走的時候其實就是設置INT3斷點,如果你選擇了使用單步硬件斷點(Use HW breakpoints for stepping)就可以在單步中避免INT3檢測了.

調試程式時暫停程式其實也是設置斷點,這裡提供了在所有線程設置斷點和使用API函數DebugBreakProcess斷點,而結束程式時候選擇使用TeminateProcess 和ExitProcess來結束程式

還有一個就是備份用戶代碼(Auto backup user code),就是備份非系統代碼段,不知道這個怎麼用,有興趣的研究一下.

調試子選項當中,增加了一個重要的內容,就是增加了解析調試符號文件的功能,如pdb,dbg等數據,它的設置在調試數據(Debiggomg data)當中

如圖


這裡你可以設置三個目錄專門存放符號文件,還可以勾選訪問Microsoft Symbol Server非常方便下載符號文件了.

在Ollydbg 1.01版當中有一個選項是Event選項,在Ollydbg 2.01版把它細分為Start 和events ,選項上大致相同的.

調試設置的其他選項可以參考1.01版來設置.

2011年8月18日星期四

Ollydbg 2.01 alpha 4 試用報告(四):選項設置(3)

搞了半天才能發帖,在Blogger轉換為舊模板形式才能使用,不知道是什麽回事,昨天我們已經看到操作數形式了,下面我們來看看轉儲(dump)窗口的代碼形式

首先我們要知道轉儲窗口在哪裡,在CPU窗口左下角的子窗口就是轉儲窗口了,
這個窗口有三項,這個窗口根據你選擇的現實形式不同而不同
而在選項菜單中的轉儲就是針對這個窗口來設置選項的

Underline fixups 下劃綫修正

而在UNICODE 轉儲使用寬字串效果對比如下

不使用

使用


在ASCII顯示時候,有些字符是非顯示形式的,用"."來代替即是勾選Replace non-printable ASCII characters with dots

不使用

使用后

轉儲還有其他選項,自己去瞭解一下吧

由於選項卡當中選項很多,如果一一說明浪費時間,而且有些內容不是很重要,所以從明天開始只是選擇重要的來說明

2011年8月17日星期三

Ollydbg 2.01 alpha 4 試用報告(四):選項設置(2)

在代碼子選項助記符(Mnemonics)中,你可以選擇一些命令顯示的形式

    命令的形式(Form of string commands)

    第二個為返回時候解碼形式(Decode near returns as)是選用RETN韓式RET

    第三個為揭秘大小靈敏的16或者32位命令助記符形式(Decode size-sensitive 16/32-bit mnemonics like):

    最後一個是跳轉提示(Decode jump hits as)


在操作數(Operands)選項當中,有兩種顯示形式選擇,

    FPU堆棧的解碼形式(Decode top of FPU stack as:)

    16位SSE操作符的大小解碼(Decode size of 16-bytes SSE operands as:)


2011年8月16日星期二

Ollydbg 2.01 alpha 4 試用報告(四):選項設置(1)

    Ollydbg 2.01插件版因為是剛剛出來,還沒有繁體中文和簡體中文版,所以我們也來看看它的選項設置有什麽內容.

Code選項:
    在Ollydbg 2.01程式選項卡的最上端是代碼(Code)以及子類選項的助記符(Mnemonics)和操作數(Operands)以及轉儲(dump)、字串(strings)设置选项.在Code选项显示如下图:
    上面第一个提供了反汇编语法单选项(Disassembling syntax),这个提供了四种编译语言的语法选择形式,它的默认MASM是我们常用的显示形式,当然如果你习惯使用IDEAL或者HLA语言形式,你也可以选择他,如果你是Linux爱好者那你选择linux吧

Masm显示:

IDEA显示:
HLA显示:
Linux显示:

在Ollydbg 2.01中反汇编指令是默认大写字母形式的,如果你习惯小写形式勾选

效果:
默认的反汇编代码选项时,助记符(如PUSH CALL JUMP)和参数(如 EBP EAX,EBX)之间靠得很近,
我们可以勾选Tab between mnemonics and arguments
未勾选:

勾选后:

如果你想在两个参数之间加大距离,勾选Extra space between arguments
未勾选:
勾选后:

后面的选项:
Show default segments 显示默认段就是代码中"DS:"此类内容
Always show size of memory operands 总是显示内存操作数大小,就是指令中的"DWORD PTR"此类内容
Show NEAR jump modifiers 显示近距离跳转,就是在近跳转指令中增加"NEAR"
Show local module name 在指令中增加当前模块名称
Show symbolic addresses 显示符号地址,就是函数等名称地址
Demangle symbolic names 解码符号名