首页
社区
课程
招聘
[原创]“不死鸟”号历险记(无厘头版)
发表于: 2009-9-3 14:06 8460

[原创]“不死鸟”号历险记(无厘头版)

2009-9-3 14:06
8460
“不死鸟”号历险记---和扫雷过不去篇(无厘头版)

程序逆向初步之二:测试环境Windows XP SP3

(警告:本文情节纯属虚构搞笑,没有讽刺任何现实国家机构的意思哦)

(建议:在看以下文字时,最好头脑浮现鸟山明阿拉蕾中漫画人物的形象以达
到较好的YY效果。)

(还是那句老话,老鸟自行飘过。)

http://album.hi.csdn.net/app_uploads/mydo/20090630/174418687.p.JPG?d=20090630174540031正义的hopy – 加菲

http://album.hi.csdn.net/app_uploads/mydo/20090630/175033078.p.JPG?d=20090630175047515 邪恶的hopy – 阿宝

xx年xx月xx日xx国的“不死鸟”号载人火箭直穿入云霄,使得正在云层中YY的鸟A与
鸟B受惊了…

   鸟A:What东东…

   鸟B:好大一根…

   与此同时,在xx国 航天中心的指挥室中…

   记者A与记者B(以下简称JA与JB)正准备采访指挥人员。

   一位长相疑似章鱼的指挥人员报告,收到‘不死鸟’号宇航员发出的信号:“我们一切OK,
感觉很Hi!”

   JA(一滴汗从后脑勺滴下):“连章鱼也…”。

   JB开始采访:“请问章鱼大叔…哦,不是…请问‘章’工,现在飞船运行情况如何?”。

   ‘章鱼’(眼睛做闪亮状):“废话,当然一切正常,飞船性能没得说,更何况还有我国
最强的双胞胎宇航员牛爱加与牛思减同志…”

   这时监控镜头切换到正在航天中心食堂拱猪的牛爱加与牛思减…

   牛A+:“你倒是快拱啊!!!”。

   牛C-:“急你个姥姥…我就不拱,你咬我”。

   JA把采访话筒指向‘章鱼’大叔:“您说的是他们两位吗?”。

   ‘章鱼’:“好小子…太不像话了…拱猪也不叫上你老哥我…”。

   JB(出汗状):“嗯?他们在地上…那在飞船上的是…”。

   章鱼’:“这个…”。

   此时在“不死鸟”飞船的船舱中,加菲与阿宝正经八百的坐在驾驶室座位上…

   阿宝:“终于混上来了…上天的美梦成真喽!”。

   加菲:“呵呵,到火星还有911天,好无聊哦,干嘛呢?”。

   阿宝:“傻了吧!幸好偶事先下载了最新的微软超大作游戏---扫雷!”。

   加菲(倒!)。

   阿宝:“谁扫雷时间用的少,谁就赢吧”。

   在加菲连输65536盘之后…

   阿宝:“没意思,你太挫了!我去WC,你好好再练练吧…嘿嘿”。

   阿宝哼着小调扭着大屁股闪进后舱WC中…

   加菲:“我不信!我不信!凭偶的IQ搞不定扫雷!我要方展博,我要方展博,我不要丁蟹,
我不要丁蟹…”。

   加菲悲愤地用IDA载入winmine.exe,熟练的下载符号文件,展开函数
表,他发现其中一个函数很有意思:

http://album.hi.csdn.net/app_uploads/mydo/20090903/125404562.p.JPG?d=20090903125418796

进入StartGame(),随即的代码让加菲眼前一亮:

.text:0100367A __stdcall StartGame() proc near         ; CODE XREF: FLocalButton(x)+CAp
.text:0100367A                                         ; DoPref()+33j
.text:0100367A                                         ; MainWndProc(x,x,x,x)+2CAp
.text:0100367A                                         ; MainWndProc(x,x,x,x):loc_1001EC8p
.text:0100367A                                         ; WinMain(x,x,x,x)+15Dp
.text:0100367A                 mov     eax, dword_10056AC
.text:0100367F                 mov     ecx, uValue
.text:01003685                 push    ebx
.text:01003686                 push    esi
.text:01003687                 push    edi
.text:01003688                 xor     edi, edi
.text:0100368A                 cmp     eax, _xBoxMac
.text:01003690                 mov     _fTimer, edi
.text:01003696                 jnz     short loc_10036A4
.text:01003696
.text:01003698                 cmp     ecx, _yBoxMac
.text:0100369E                 jnz     short loc_10036A4
.text:0100369E
.text:010036A0                 push    4
.text:010036A2                 jmp     short loc_10036A6
.text:010036A2
.text:010036A4 ; ---------------------------------------------------------------------------
.text:010036A4
.text:010036A4 loc_10036A4:                            ; CODE XREF: StartGame()+1Cj
.text:010036A4                                         ; StartGame()+24j
.text:010036A4                 push    6
.text:010036A4
.text:010036A6
.text:010036A6 loc_10036A6:                            ; CODE XREF: StartGame()+28j
.text:010036A6                 pop     ebx
.text:010036A7                 mov     _xBoxMac, eax
.text:010036AC                 mov     _yBoxMac, ecx
.text:010036B2                 call    ClearField()
.text:010036B2
.text:010036B7                 mov     eax, dword_10056A4
.text:010036BC                 mov     _iButtonCur, edi
.text:010036C2                 mov     _cBombStart, eax
.text:010036C2
.text:010036C7
.text:010036C7 loc_10036C7:                            ; CODE XREF: StartGame()+74j
.text:010036C7                                         ; StartGame()+89j
.text:010036C7                 push    _xBoxMac
.text:010036CD                 call    Rnd(x)
.text:010036CD
.text:010036D2                 push    _yBoxMac
.text:010036D8                 mov     esi, eax
.text:010036DA                 inc     esi
.text:010036DB                 call    Rnd(x)
.text:010036DB
.text:010036E0                 inc     eax
.text:010036E1                 mov     ecx, eax
.text:010036E3                 shl     ecx, 5
.text:010036E6                 test    byte ptr _rgBlk[ecx+esi], 80h
.text:010036EE                 jnz     short loc_10036C7
.text:010036EE
.text:010036F0                 shl     eax, 5
.text:010036F3                 lea     eax, _rgBlk[eax+esi]
.text:010036FA                 or      byte ptr [eax], 80h
.text:010036FD                 dec     _cBombStart
.text:01003703                 jnz     short loc_10036C7
.text:01003703
.text:01003705                 mov     ecx, _yBoxMac
.text:0100370B                 imul    ecx, _xBoxMac
.text:01003712                 mov     eax, dword_10056A4
.text:01003717                 sub     ecx, eax        ; int
.text:01003719                 push    edi
.text:0100371A                 mov     _cSec, edi
.text:01003720                 mov     _cBombStart, eax
.text:01003725                 mov     _cBombLeft, eax
.text:0100372A                 mov     _cBoxVisit, edi
.text:01003730                 mov     _cBoxVisitMac, ecx
.text:01003736                 mov     _fStatus, 1
.text:01003740                 call    UpdateBombCount(x)
.text:01003740
.text:01003745                 push    ebx             ; int
.text:01003746                 call    AdjustWindow(x)
.text:01003746
.text:0100374B                 pop     edi
.text:0100374C                 pop     esi
.text:0100374D                 pop     ebx
.text:0100374E                 retn
.text:0100374E
.text:0100374E __stdcall StartGame() endp


通过简单的大脑分析,加菲很快得出了扫雷的硬性参数限定:


   初级 9 * 9 共 10 个雷
中级 16 * 16 共 40 个雷
高级 30 * 16 共 99 个雷
自定义 x * y 共 z 个雷 (最大不超过30 * 24 , 667个雷,
最小不小于9 * 9,10个雷)

    再经过一番思索,并不十分擅长动脑子的加菲也渐渐理出StartGame中各个变量
大致意思:

   _rbBlk(0x1005340)
一个字节全局数组,存放的是每个box的内部表示。
如果字节最高位置1则表示其中有一个雷哦(or 0x80)
bomb(x,y) =_rbBlk[x + y * 32]。x和y下标从1开始,
最大值上面给出了,由于rnd返回的数下标从0开始,故
使用前要加1。

   _cSec(0x100579C)
已过时间(秒)

   _cBombStart(0x1005330)
总雷数

   _cBombLeft(0x1005194)
剩下未扫的雷数

   _cBoxVisit(0x10057A4)
已揭开的box数

   _cBoxVisitMac(0x10057A0)
总box数 - 藏有雷的box数

   接着,加菲用毛茸茸的爪子捏着鼻子,盘算起这段代码的大致含义来:
很明显,代码用当前格子的行数和列数初始化_xBoxMac与_yBoxMac变量,
然后清除“雷区”为下面的“布雷”做准备。后面代码“图懒”调用了
msvcrt.dll中的Rnd函数,可以清楚地看见,Rnd在_xBoxMac与
_yBoxMac的范围内生成地雷的坐标,然后将对应地雷的标志写入
_rgBlk地址开始的结构数组中去,这样不断循环直到未布地雷
个数_cBombStart为0为止。最后代码使用UpdateBombCount
更形地雷数量。

   知道了这些,加菲觉得有了些胸有成竹、波涛汹涌的感觉。为了快速解决
战斗,加菲采用了一些变量硬编码的技术,他当然知道这个对于不同版本的扫雷
来说就没有通用性喽。

//检查当前扫雷进程是否运行
DWORD FindProcess(const char *szName)
{
 DWORD pid = 0;
 
 if(!szName)
  goto QUIT;
 
 PROCESSENTRY32 process = {.dwSize = sizeof(PROCESSENTRY32)};
 HANDLE hss = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
 Process32First(hss,&process);
 do
 {
  if(!strcmp(process.szExeFile,szName))
  {
   pid = process.th32ProcessID;
   break;
  }
 }while(Process32Next(hss,&process));
 
 CloseHandle(hss);
QUIT:
 return pid;
}
 
//检查将要fix的扫雷版本是否正确
bool IsSignWM(DWORD pid)
{
 bool bSuccess = false;
 HANDLE hp = NULL;
 if(!pid)
  goto QUIT;
 
 byte bin[SINGSIZE];
 hp = OpenProcess(PROCESS_ALL_ACCESS,false,pid);
 if(!hp)
  goto QUIT;
 if(!ReadProcessMemory(hp,(LPCVOID)SIGNADDR,bin,sizeof(bin),\
  NULL))
  goto QUIT;
 if(memcmp(bin,sign,SINGSIZE) == 0)
  bSuccess = true;
QUIT:
 if(hp)
  CloseHandle(hp);
 return bSuccess;
}
 
//将已过时间清零
void ZeroTime(DWORD pid)
{
 HANDLE hp = OpenProcess(PROCESS_ALL_ACCESS,false,pid);
 if(!hp)
  goto QUIT;
 int ZeroSec = 0;
 if(!WriteProcessMemory(hp,(LPVOID)p_cSec,&ZeroSec,sizeof(int),\
  NULL))
  goto QUIT;
 puts("Zero Time Success!");
QUIT:
 if(hp)
  CloseHandle(hp);
 return;
}
 
//显示地雷的布局
void ShowBombs(DWORD pid)
{
 HANDLE hp = OpenProcess(PROCESS_ALL_ACCESS,false,pid);
 if(!hp)
  goto QUIT;
 
 int xMax,yMax,BombCount;
 if(!ReadProcessMemory(hp,(LPCVOID)p_xBoxMac,&xMax,sizeof(int),\
  NULL))
  goto QUIT;
 
 if(!ReadProcessMemory(hp,(LPCVOID)p_yBoxMac,&yMax,sizeof(int),\
  NULL))
  goto QUIT;
 if(!ReadProcessMemory(hp,(LPCVOID)p_cBombStart,&BombCount,\
  sizeof(int),NULL))
  goto QUIT;
 printf("Bomb Count is %d , xmax is %d , ymax is %d\n",\
  BombCount,xMax,yMax);
 
 //byte Bombs[xMax][yMax];
 //byte Bombs[9][9];
 byte *Bombs = (byte*)malloc((xMax<<5)+yMax+1);
 if(!Bombs)
  goto QUIT;
 
 //DWORD tmp = (DWORD)p_rbBlk + 0x21;
 if(!ReadProcessMemory(hp,(LPCVOID)p_rbBlk,Bombs,(xMax<<5)+yMax+1,\
  NULL))
  goto QUIT;
 for(int x = 1;x <= yMax;++x)
 {
  for(int y = 1;y <= xMax;++y)
  {
   if(Bombs[(x<<5)+y]/*Bombs[x][y]*/ & 0x80)
    putchar('*');
   else
    putchar('N');
  }
  puts("");
 }
QUIT:
 if(hp)
  CloseHandle(hp);
 if(Bombs)
  free(Bombs);
 return;
}


作为收尾工作,加菲写了一个控制台的command代码去解决人机交互问题:


int main(void)
{
 if(!SetDebugPrivilege(true))
  puts("Set Debug Privilege Failed!");
 
 DWORD pid = FindProcess("winmine.exe");
 if(!pid)
 {
  pid = FindProcess("MineSweeper.exe");
  if(!pid)
  {
   puts("winmine.exe is not running!");
   goto QUIT;
  }
 }
 
 if(!IsSignWM(pid))
 {
  puts("error ver of winmine.exe!");
  goto QUIT;
 }
 
 int c;
 do
 {
  puts("How Do You Want Play With WinMine???");
  printf("v: show bombs view z: zero time q: quit :: ");
  c = getchar();
  switch(c)
  {
  case 'v':
  case 'V':
   printf("ShowBombs At %p\n",(void*)ShowBombs);
   ShowBombs(pid);
   break;
  case 'z':
  case 'Z':
   ZeroTime(pid);
   break;
  case 'q':
  case 'Q':
   puts("Quit! Have Funs...");
   goto QUIT;
   break;
  default:
   puts("unknow command , try again.");
   break;
  }
  fflush(stdin);
 }while(true);
QUIT:
 fflush(stdin);
 (void)getchar();
 return 0;
}
http://album.hi.csdn.net/app_uploads/mydo/20090903/134155421.p.JPG?d=20090903134204750

加菲(用力擦了一把头上的汗):“搞定了,等会还不赢死你...嘿嘿...咦...怎么阿宝去
WC这么长时间都没回来,搞什么飞机???”。

   加菲走到太空床前,一屁股睡倒。他想边躺着边等阿宝,结果一不小心
睡过去了...

   与此同时,“不死鸟”号的WC内的真空马桶内...

   由于控制WC真空马桶的Wxxs系统死机崩溃,导致可怜的阿宝被密封在
自己的排泄物和呕吐物中N个小时了,他还在焦急地等待着加菲前来拯救自己,
可是...

   加菲在床上做了一个梦,梦见阿宝憋屈在马桶里对他吼着什么,
加菲甜美的笑了:“这次终于赢你啦!”。(本篇完)

   (对于正在吃饭或准备要吃饭的朋友,如果破坏了你的食欲,我对此深表歉意,
我也觉得有点恶心,厚厚!)
(有兴趣的朋友可以观赏偶的前一篇无厘头作品:
【原创】和Taskmgr过不去篇(无厘头版)
http://bbs.pediy.com/showthread.php?p=649050#post649050)

[课程]Android-CTF解题方法汇总!

上传的附件:
收藏
免费 7
支持
分享
最新回复 (9)
雪    币: 202
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
沙发学习+膜拜
2009-9-3 14:19
0
雪    币: 14983
活跃值: (5285)
能力值: ( LV15,RANK:880 )
在线值:
发帖
回帖
粉丝
3
哈哈,这个有意思,风趣。也学到不少东西。
以后建议多发这类文章。
2009-9-3 14:26
0
雪    币: 7115
活跃值: (639)
能力值: (RANK:1290 )
在线值:
发帖
回帖
粉丝
4
不错。。。 不错。。。 这样的帖子看起来很有趣。。。 不累。。。 继续继续。。。
2009-9-3 14:29
0
雪    币: 234
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
楼主想搞笑。。。
2009-9-3 16:21
0
雪    币: 247
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
呵呵
真正的娱乐中学习
2009-9-3 16:29
0
雪    币: 1844
活跃值: (35)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
7
我来支持啊宝的
2009-9-3 16:32
0
雪    币: 716
活跃值: (162)
能力值: ( LV9,RANK:250 )
在线值:
发帖
回帖
粉丝
8
支持无厘头版,呵呵
2009-9-3 17:40
0
雪    币: 442
活跃值: (107)
能力值: ( LV9,RANK:350 )
在线值:
发帖
回帖
粉丝
9
迟来的精华???
2010-2-11 14:53
0
雪    币: 247
活跃值: (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
10
图看不了= =
2010-2-11 16:08
0
游客
登录 | 注册 方可回帖
返回
//