首页
论坛
课程
招聘
[原创]含沙量高的->连连看v3.0 游戏修改器
2007-6-18 10:04 12933

[原创]含沙量高的->连连看v3.0 游戏修改器

2007-6-18 10:04
12933
└文章标题┐:连连看v3.0 小试逆向and游戏修改器
└破文作者┐:大菜一号
└破解对象┐:连连看v3.0
└下载地址┐:不知道
└对象大小┐:不知道
└加壳方式┐:upx
└保护方式┐:说是逆向啦!
└编写语言┐:vb
└使用工具┐:OD
└破解平台┐:D-XP
└破解声明┐:逆向也不错:)
----------------------------------------------------------------------------------
└破解过程┐:
  这个游戏好像不太好找了!找到的都是4.0的,呵呵,压了也有3m多,所以临时做了个精简版,压了之后有788k,传上来了!
  从未做过游戏修改器也,说也简单,找到地址,然后WriteProcessMemory一下就行!主要是如何找地址!这个程序脱壳upx老牌子衣服之后,可以看到它是用VB做的!呵呵``代码就有点乱罢了!

  游戏介绍一下:
  一共有11关,从0关到第10关,除了第0关游戏图片不会动之外,其它的要不就是整体向上,向左,左上右下什么什么的!很是烦!

  玩一下游戏,发现几处想改的地方:
1、重新洗牌数
2、提示数
3、跳关
4、提示数不想让程序减了
5、洗牌数也不想让程序减了
6、提示数用完之后,那个菜单会变灰,就算我们用游戏修改器加了提示数,也一样,所以,这里也不想让它变灰了!
7、重新洗牌数用完之后就Game Over,没注意看洗牌数为0时,再使用就Game Over,而不像提示数那个可以变灰!我们就不让它Game Over!
好了,要改的就这么些地方,有人要问了,连连看都有时间限制的吧,你怎么不改时间,让它停住不动,这要改很简单!只不过,改了的话就要被人bs了!!呵呵~~这里就放弃吧!

  好,脱掉upx之后,用OD载入,提示加壳(汗,我想修正一下ep段就不会了吧):

一、找提示数地址:
  我们发现游戏有三个难度(easy,normal,hard),简单,正常和因难三种!就有了这三个关键字,我们用w32dasm载入,查找到字符串easy,双击之后发现多处调用,当然这里是试用出来的!到这:
00489480    55              push    ebp                             
00489481    8BEC            mov     ebp, esp
00489483    83EC 08         sub     esp, 8
00489486    68 861D4000     push    <jmp.&MSVBVM60.__vbaExceptHandle>
0048948B    64:A1 00000000  mov     eax, dword ptr fs:[0]
00489491    50              push    eax
00489492    64:8925 0000000>mov     dword ptr fs:[0], esp
00489499    81EC EC000000   sub     esp, 0EC
0048949F    53              push    ebx
004894A0    56              push    esi
004894A1    57              push    edi
004894A2    8965 F8         mov     dword ptr [ebp-8], esp
004894A5    C745 FC 0017400>mov     dword ptr [ebp-4], 00401700
004894AC    8B15 B0314A00   mov     edx, dword ptr [4A31B0]
004894B2    33F6            xor     esi, esi
004894B4    8D8D 24FFFFFF   lea     ecx, dword ptr [ebp-DC]
004894BA    8975 E4         mov     dword ptr [ebp-1C], esi
004894BD    8975 E8         mov     dword ptr [ebp-18], esi
004894C0    8975 DC         mov     dword ptr [ebp-24], esi
004894C3    8975 E0         mov     dword ptr [ebp-20], esi
004894C6    8975 D0         mov     dword ptr [ebp-30], esi
004894C9    8975 CC         mov     dword ptr [ebp-34], esi
004894CC    8975 C8         mov     dword ptr [ebp-38], esi
004894CF    8975 C4         mov     dword ptr [ebp-3C], esi
004894D2    8975 C0         mov     dword ptr [ebp-40], esi
004894D5    8975 B0         mov     dword ptr [ebp-50], esi
004894D8    8975 A0         mov     dword ptr [ebp-60], esi
004894DB    8975 90         mov     dword ptr [ebp-70], esi
004894DE    8975 80         mov     dword ptr [ebp-80], esi
004894E1    89B5 70FFFFFF   mov     dword ptr [ebp-90], esi
004894E7    89B5 60FFFFFF   mov     dword ptr [ebp-A0], esi
004894ED    89B5 50FFFFFF   mov     dword ptr [ebp-B0], esi
004894F3    89B5 3CFFFFFF   mov     dword ptr [ebp-C4], esi
004894F9    89B5 24FFFFFF   mov     dword ptr [ebp-DC], esi
004894FF    66:8935 CE304A0>mov     word ptr [4A30CE], si
00489506    8935 34314A00   mov     dword ptr [4A3134], esi
0048950C    8935 58314A00   mov     dword ptr [4A3158], esi
00489512    FF15 B4114000   call    dword ptr [<&MSVBVM60.__vbaStrCo>; MSVBVM60.__vbaStrCopy
00489518    8B85 24FFFFFF   mov     eax, dword ptr [ebp-DC]
0048951E    8B3D F4104000   mov     edi, dword ptr [<&MSVBVM60.__vba> ; __vbaStrCmp的rva传给edi,主要是供下面的call调用
00489524    50              push    eax                               ; 关键字"easy"进栈
00489525    68 5C6C4000     push    00406C5C                          ; 点击的菜单项的标题进栈
0048952A    FFD7            call    edi                               ; 比较,所取得的信息是否为"easy"
0048952C    85C0            test    eax, eax                          ; 返回值是否为空
0048952E    75 1E           jnz     short 0048954E                    ; 不为空则所取信息不为"easy"
00489530    C705 D0304A00 0>mov     dword ptr [4A30D0], 43480000      ; 所选难度为easy,则在这里初始化游戏
0048953A    66:C705 94314A0>mov     word ptr [4A3194], 4              ; 提示次数传给004a3194
00489543    66:C705 D4304A0>mov     word ptr [4A30D4], 2              ; 洗牌次数传到004a30d4
0048954C    EB 5E           jmp     short 004895AC                    ; 跳过后面中级高级难度的比较
0048954E    8B8D 24FFFFFF   mov     ecx, dword ptr [ebp-DC]         
00489554    51              push    ecx
00489555    68 6C6C4000     push    00406C6C                         ; 如果不为easy级别,则到这里,normal关键进栈
0048955A    FFD7            call    edi                              ; 调用__vbaStrCmp
0048955C    85C0            test    eax, eax                         ; 是否为normal
0048955E    75 1E           jnz     short 0048957E                   ; 不是就跳
00489560    C705 D0304A00 0>mov     dword ptr [4A30D0], 43480000     ; 是normal级别就在这里初始化游戏
0048956A    66:C705 94314A0>mov     word ptr [4A3194], 6             ; 提示次数赋值
00489573    66:C705 D4304A0>mov     word ptr [4A30D4], 3             ; 洗牌次数赋值
0048957C    EB 2E           jmp     short 004895AC
0048957E    8B95 24FFFFFF   mov     edx, dword ptr [ebp-DC]
00489584    52              push    edx
00489585    68 806C4000     push    00406C80                         ; 如果不为normal和easy级别就到这里
0048958A    FFD7            call    edi                              ; 调用__vbaStrCmp
0048958C    85C0            test    eax, eax                         ; 是否为hard
0048958E    75 1C           jnz     short 004895AC                   ; 不等就跳
00489590    C705 D0304A00 0>mov     dword ptr [4A30D0], 43700000     ; 是hard就初始化游戏
0048959A    66:C705 94314A0>mov     word ptr [4A3194], 8             ; 提示次数赋值
004895A3    66:C705 D4304A0>mov     word ptr [4A30D4], 4             ; 洗牌次数赋值
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
我们可以知道,提示数的地址为4a3194,洗牌数地址为4a30d4
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

二、找跳关,扣除提示数和洗牌数的地址:
  我们知道提示数和洗牌数的地址了,如果游戏要扣除它们的话,就会访问并写进数据,我们在命令下d 4a3194,在第一字节上下内存写入断点,再d 4a30d4,在第一字节上下内存写入断点!这样游戏扣除提示数和洗牌数时我们就可以知道在什么地方了!

  运行游戏,使用一次提示数,就到达这里:
004A17F0    66:8B0D 94314A0>mov     cx, word ptr [4A3194]            ; 把提示数传给cx
004A17F7    BA 38884000     mov     edx, 00408838
004A17FC    66:83E9 01      sub     cx, 1                            ; 倒扣提示数(使用一次当然是减一)
004A1800    C745 E0 D000000>mov     dword ptr [ebp-20], 0D0
004A1807    0F80 A3080000   jo      004A20B0                         ; jo->真是讨厌!
004A180D    66:890D 94314A0>mov     word ptr [4A3194], cx            ; 传回去!

再使用一次洗牌数:
00485AC7    66:A1 D4304A00  mov     ax, word ptr [4A30D4]            ; 把洗牌数传给ax
00485ACD    66:2D 0100      sub     ax, 1                            ; 倒扣洗牌次数
00485AD1    0F80 68020000   jo      00485D3F                         ; 又是jo
00485AD7    66:3BC3         cmp     ax, bx                           ; 洗牌次数是否归0(是否游戏失败)
00485ADA    66:A3 D4304A00  mov     word ptr [4A30D4], ax            ; 传回去!
00485AE0    0F8D C3010000   jge     00485CA9

  我们不取消上面下的内存写入断点,继续把游戏玩到第二关,第一关所有图片都消除后,游戏会给你加一次洗牌数和提示数,这时又会往提款数和洗牌数地址里写入东西!我们又断下了:
004842AC    66:A1 CE304A00  mov     ax, word ptr [4A30CE]            ;[4a30ce]里的内容是0,传给ax
004842B2    66:8B0D D4304A0>mov     cx, word ptr [4A30D4]            ;洗牌数传给cx
004842B9    66:8B15 94314A0>mov     dx, word ptr [4A3194]            ;提示数传给dx
004842C0    33F6            xor     esi, esi
004842C2    8B7D 08         mov     edi, dword ptr [ebp+8]
004842C5    66:05 0100      add     ax, 1                            ;ax+1(关数加一)
004842C9    0F80 5A170000   jo      00485A29
004842CF    66:83C1 01      add     cx, 1                            ;洗牌数加一
004842D3    66:A3 CE304A00  mov     word ptr [4A30CE], ax            ;传回去
004842D9    0F80 4A170000   jo      00485A29
004842DF    66:83C2 01      add     dx, 1                            ;提示数加一
004842E3    66:890D D4304A0>mov     word ptr [4A30D4], cx            ;传回去
004842EA    0F80 39170000   jo      00485A29

一路f8下来会到这:
00484430    66:833D CE304A0>cmp     word ptr [4A30CE], 0B            ; 比较是否过完全部的11关
00484438    68 94314A00     push    004A3194
0048443D    68 D0304A00     push    004A30D0
00484442    68 48314A00     push    004A3148
00484447    68 D4304A00     push    004A30D4
0048444C    68 CE304A00     push    004A30CE
00484451    0F8D 81030000   jge     004847D8                         ; 是就恭喜你一下!
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
我们又可以知道程序是在004a17fc上扣除提示数的,在485acd上扣除洗牌数的,在4a30ce上表示关数的!
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

三、不让提示数归0时菜单项变灰:
用VBExplorer找到点击菜单事件代码,来到这里:
00486C24    FFD3            call    ebx
00486C26    66:833D 94314A0>cmp     word ptr [4A3194], 0             ;[4a3194]是提示数地址,和0比较
00486C2E    8B16            mov     edx, dword ptr [esi]
00486C30    56              push    esi
00486C31    7F 23           jg      short 00486C56                   ;小于就不跳,就变灰

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
知道jg是关键跳,改为jmp就不会变灰了!
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

四、洗牌数归0时也不会Game Over:
再次来到扣除洗牌数的地方:
00485ACD    66:2D 0100      sub     ax, 1                            ; 倒扣洗牌次数地址
00485AD1    0F80 68020000   jo      00485D3F
00485AD7    66:3BC3         cmp     ax, bx                           ; 洗洗牌次数是否归0(是否游戏失败)
00485ADA    66:A3 D4304A00  mov     word ptr [4A30D4], ax            
00485AE0    0F8D C3010000   jge     00485CA9                         ; 小于就Game Over;

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
知道jge是关键跳,改为jmp就不会变灰了!
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

要找的就这么多,简单吧!记下机器码,要改的机器码不知道的话可以在OD中改成想要的代码,变红的就是改变了的机器码了,一个字节一个字节的记下来,接下来,,我们用mfc实现游戏修改器吧:

定义变量:
public:
        int radio;
        BOOL if_edit_1,if_edit_2;
        int tishi,xipia,i;//定义用户输入的洗牌数和提示数,一个临时变量
        DWORD ProcessID;//进程ID
        HANDLE hProcess;//进程句柄
        HWND hwnd;//窗口句柄
        BYTE tishi_edit,tishi_1,tishi_2,tishi_3,tishi_4,
                tishi_5,tishi_6,tishi_7,tishi_8;//写入提示不减时的机器码
        BYTE xipia_edit,xipia_1,xipia_2,xipia_3,xipia_4;
        BYTE game_over_1,game_over_2,game_over_3
                ,game_over_4,game_over_5,game_over_6,game_over_edit1,
                game_over_edit2,
                game_over_edit3,
                game_over_edit4,
                game_over_edit5,
                game_over_edit6;//程序game_over时要写入的机器码和原始数据
        BYTE tishi_menu_gray,tishi_menu;//菜单变灰的数据

构造函数中变量赋值:
hProcess=NULL;
        hwnd=NULL;
        i=0;
        ProcessID=0;
        tishi=0;
        xipia=0;
       
        tishi_edit=0x90;//------------给提示不减的机器码赋值
       
        if_edit_1=FALSE;
        if_edit_2=FALSE;
        radio=0;
        z=FALSE;
        game_over_edit1=0x90;//在OD中所记下的一点机器码
        game_over_edit2=0x00;
        game_over_edit3=0x00;
        game_over_edit4=0x01;
        game_over_edit5=0xc4;
        game_over_edit6=0xe9;

        tishi_menu_gray=0xeb;
//至于其它,我们用读的:

对话框初始化OnInitDialog()函数:
        hwnd=::FindWindow(0,"连连看v3.0");
        if(hwnd==0)
        {
                MessageBox("游戏并没有运行!",NULL,MB_OK | MB_ICONWARNING);
                CKawai3EditDlg::OnCancel();
        }
        else
        {
        GetWindowThreadProcessId(hwnd,&ProcessID);
        hProcess=::OpenProcess(PROCESS_ALL_ACCESS,FALSE,ProcessID);
        if(hProcess==NULL)
        {
                MessageBox("打开进程失败!",NULL,MB_OK | MB_ICONWARNING);
                CKawai3EditDlg::OnCancel();
        }
        //先保存一下数据,以便用户恢复
        //保存原先提示不减数据
        ReadProcessMemory(hProcess,(LPCVOID)0x004a17fc,&tishi_1,1,NULL);
        ReadProcessMemory(hProcess,(LPCVOID)0x004a17fd,&tishi_2,1,NULL);
        ReadProcessMemory(hProcess,(LPCVOID)0x004a17fe,&tishi_3,1,NULL);
        ReadProcessMemory(hProcess,(LPCVOID)0x004a17ff,&tishi_4,1,NULL);
        ReadProcessMemory(hProcess,(LPCVOID)0x00486b71,&tishi_5,1,NULL);
        ReadProcessMemory(hProcess,(LPCVOID)0x00486b72,&tishi_6,1,NULL);
        ReadProcessMemory(hProcess,(LPCVOID)0x00486b73,&tishi_7,1,NULL);
        ReadProcessMemory(hProcess,(LPCVOID)0x00486b74,&tishi_8,1,NULL);
        //保存存原先洗牌不减数据
        ReadProcessMemory(hProcess,(LPVOID)0x485acd,&xipia_1,1,NULL);
        ReadProcessMemory(hProcess,(LPVOID)0x485ace,&xipia_2,1,NULL);
        ReadProcessMemory(hProcess,(LPVOID)0x485acf,&xipia_3,1,NULL);
        ReadProcessMemory(hProcess,(LPVOID)0x485ad0,&xipia_4,1,NULL);
        //保存原先洗牌数为0时也不Game Over数据
        ReadProcessMemory(hProcess,(LPVOID)0x485ae0,&game_over_1,1,NULL);
        ReadProcessMemory(hProcess,(LPVOID)0x485ae1,&game_over_2,1,NULL);
        ReadProcessMemory(hProcess,(LPVOID)0x485ae2,&game_over_3,1,NULL);
        ReadProcessMemory(hProcess,(LPVOID)0x485ae3,&game_over_4,1,NULL);
        ReadProcessMemory(hProcess,(LPVOID)0x485ae4,&game_over_5,1,NULL);
        ReadProcessMemory(hProcess,(LPVOID)0x485ae5,&game_over_6,1,NULL);
        //保存原先菜单会变灰的数据
        ReadProcessMemory(hProcess,(LPVOID)0x486af3,&tishi_menu,1,NULL);
        }
游戏修改过程:
void CKawai3EditDlg::OnOK()
{
        // TODO: Add extra validation here
        tishi=GetDlgItemInt(IDC_EDIT1);
        xipia=GetDlgItemInt(IDC_EDIT2);
        WriteProcessMemory(hProcess,(LPVOID)0x004a3194,&tishi,4,NULL);
        WriteProcessMemory(hProcess,(LPVOID)0x004a30d4,&xipia,4,NULL);
                               
        if((GetDlgItem(IDC_CHECK1)->SendMessage(BM_GETCHECK,0,0))>0)
        {                                               
                WriteProcessMemory(hProcess,(LPVOID)0x004a17fc,&tishi_edit,1,NULL);
                WriteProcessMemory(hProcess,(LPVOID)0x004a17fd,&tishi_edit,1,NULL);
                WriteProcessMemory(hProcess,(LPVOID)0x004a17fe,&tishi_edit,1,NULL);
                WriteProcessMemory(hProcess,(LPVOID)0x004a17ff,&tishi_edit,1,NULL);
                                        //使用提示数不减                       
                WriteProcessMemory(hProcess,(LPVOID)0x00486b71,&tishi_edit,1,NULL);
                WriteProcessMemory(hProcess,(LPVOID)0x00486b72,&tishi_edit,1,NULL);
                WriteProcessMemory(hProcess,(LPVOID)0x00486b73,&tishi_edit,1,NULL);
                WriteProcessMemory(hProcess,(LPVOID)0x00486b74,&tishi_edit,1,NULL);
        }
        else//没选中'提示不减'的话,就恢复
        {
                WriteProcessMemory(hProcess,(LPVOID)0x004a17fc,&tishi_1,1,NULL);
                WriteProcessMemory(hProcess,(LPVOID)0x004a17fd,&tishi_2,1,NULL);
                WriteProcessMemory(hProcess,(LPVOID)0x004a17fe,&tishi_3,1,NULL);
                WriteProcessMemory(hProcess,(LPVOID)0x004a17ff,&tishi_4,1,NULL);
                WriteProcessMemory(hProcess,(LPVOID)0x00486b71,&tishi_5,1,NULL);
                WriteProcessMemory(hProcess,(LPVOID)0x00486b72,&tishi_6,1,NULL);
                WriteProcessMemory(hProcess,(LPVOID)0x00486b73,&tishi_7,1,NULL);
                WriteProcessMemory(hProcess,(LPVOID)0x00486b74,&tishi_8,1,NULL);
        }

        if(GetDlgItem(IDC_CHECK2)->SendMessage(BM_GETCHECK,0,0)>0)//是否选中洗牌数不减
        {
                                        //先读出来,以便恢复
                                       
                WriteProcessMemory(hProcess,(LPVOID)0x485acd,&tishi_edit,1,NULL);
                WriteProcessMemory(hProcess,(LPVOID)0x485ace,&tishi_edit,1,NULL);
                WriteProcessMemory(hProcess,(LPVOID)0x485acf,&tishi_edit,1,NULL);
                WriteProcessMemory(hProcess,(LPVOID)0x485ad0,&tishi_edit,1,NULL);
        }
        else//没选中就恢复数据
        {
                WriteProcessMemory(hProcess,(LPVOID)0x485acd,&xipia_1,1,NULL);
                WriteProcessMemory(hProcess,(LPVOID)0x485ace,&xipia_2,1,NULL);
                WriteProcessMemory(hProcess,(LPVOID)0x485acf,&xipia_3,1,NULL);
                WriteProcessMemory(hProcess,(LPVOID)0x485ad0,&xipia_4,1,NULL);
        }

        if(GetDlgItem(IDC_CHECK3)->SendMessage(BM_GETCHECK,0,0)>0)
                //是否选中洗牌数归0也不game over
        {
                WriteProcessMemory(hProcess,(LPVOID)0x485ae0,&game_over_edit6,1,NULL);
                WriteProcessMemory(hProcess,(LPVOID)0x485ae1,&game_over_edit5,1,NULL);
                WriteProcessMemory(hProcess,(LPVOID)0x485ae2,&game_over_edit4,1,NULL);
                WriteProcessMemory(hProcess,(LPVOID)0x485ae3,&game_over_edit3,1,NULL);
                WriteProcessMemory(hProcess,(LPVOID)0x485ae4,&game_over_edit2,1,NULL);
                WriteProcessMemory(hProcess,(LPVOID)0x485ae5,&game_over_edit1,1,NULL);
        }
        else//没选中就恢复数据
        {
                WriteProcessMemory(hProcess,(LPVOID)0x485ae0,&game_over_1,1,NULL);
                WriteProcessMemory(hProcess,(LPVOID)0x485ae1,&game_over_2,1,NULL);
                WriteProcessMemory(hProcess,(LPVOID)0x485ae2,&game_over_3,1,NULL);
                WriteProcessMemory(hProcess,(LPVOID)0x485ae3,&game_over_4,1,NULL);
                WriteProcessMemory(hProcess,(LPVOID)0x485ae4,&game_over_5,1,NULL);
                WriteProcessMemory(hProcess,(LPVOID)0x485ae5,&game_over_6,1,NULL);
        }

        if(GetDlgItem(IDC_CHECK4)->SendMessage(BM_GETCHECK,0,0)>0)//是否让提示菜单变灰
        {
                WriteProcessMemory(hProcess,(LPVOID)0x486c31,&tishi_menu_gray,1,NULL);
                WriteProcessMemory(hProcess,(LPVOID)0x486af3,&tishi_menu_gray,1,NULL);
        }
        else
        {
                WriteProcessMemory(hProcess,(LPVOID)0x486af3,&tishi_menu,1,NULL);
                WriteProcessMemory(hProcess,(LPVOID)0x486c31,&tishi_menu,1,NULL);
        }
        WriteProcessMemory(hProcess,(LPVOID)0x004a30ce,&radio,1,NULL);//跳关
}

        //CDialog::OnOK();

void CKawai3EditDlg::OnRadio1()
{
        // TODO: Add your control notification handler code here
        radio=0;
}

void CKawai3EditDlg::OnRadio2()
{
        // TODO: Add your control notification handler code here
        radio=1;
}

void CKawai3EditDlg::OnRadio3()
{
        // TODO: Add your control notification handler code here
        radio=2;
}

void CKawai3EditDlg::OnRadio4()
{
        // TODO: Add your control notification handler code here
        radio=3;
}

void CKawai3EditDlg::OnRadio5()
{
        // TODO: Add your control notification handler code here
        radio=4;
}

void CKawai3EditDlg::OnRadio6()
{
        // TODO: Add your control notification handler code here
        radio=5;
}

void CKawai3EditDlg::OnRadio7()
{
        // TODO: Add your control notification handler code here
        radio=6;
}

void CKawai3EditDlg::OnRadio8()
{
        // TODO: Add your control notification handler code here
        radio=7;
}

void CKawai3EditDlg::OnRadio9()
{
        // TODO: Add your control notification handler code here
        radio=8;
}

void CKawai3EditDlg::OnRadio10()
{
        // TODO: Add your control notification handler code here
        radio=9;
}

void CKawai3EditDlg::OnRadio11()
{
        // TODO: Add your control notification handler code here
        radio=10;
}

void CKawai3EditDlg::OnCancel()
{
        // TODO: Add extra cleanup here
       
        CDialog::OnCancel();
}

void CKawai3EditDlg::OnClose()
{
        // TODO: Add your message handler code here and/or call default
        CloseHandle(hProcess);  //关闭进程句柄
        CDialog::OnClose();
}

好了好了``就这样完了!!很简单的东西~~
对了,这个游戏的流程我也稍微跟了一下,没有个确切的结果,不放上来给大家看了!就是点击图片时游戏作出的反映,也就是游戏如何判断两个图片是否相同,路径是否可通过,是否可在窗口上消除这两个图片。
大家可以bp CreateThread,在创建线程函数上下数,当点击一个图片时就会断下了!
有兴趣的朋友可以逆一下,大致来说(我跟了一下),是这样:
先取出第一次点击的图片的位置,和12比较,(easy级别图片版面横向只有12张),看看是否超越下标界限!
没有的话经过算一算,得出结果a,再取出第二次点击的图片的位置,再看看是否超越下标界限,没有的话再算一算,得到结果b;
两结果比较,相等的话再算一下路径是否可通过,可通过就消除这两张图片!

就这样!!~~呵呵~~
可能不太对,,- -B``
还有哇`这个游戏修改器修改提示数和洗牌数时我没限制的,改太多的话jo这家伙就溢出了!~~
所以``大家小心啦!呵呵呵呵~~
----------------------------------------------------------------------------------
└经验总结┐:
  我本来想做个专业的自动连连器的,就像扫雷器一样,不过跟踪VB程序是在是太烦了!!想想还是和弃了,有耐心的朋友可以一试,弄懂算法就可以了!呵呵~~先这样吧!
  
  中考摧残身心之娱乐之作!!呵呵~
----------------------------------------------------------------------------------
└版权声明┐ 本文原创于看雪软件安全论坛, 转载请注明作者并保持文章的完整, 谢谢!
                                                           2007年6月17日  20:30:41

[公告]名企招聘!

上传的附件:
收藏
点赞0
打赏
分享
最新回复 (19)
雪    币: 89
活跃值: 活跃值 (20)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
kenmark 活跃值 2 2007-6-18 10:19
2
0
正好我老爸烦死了要我写一个破解工具,谢谢LZ!!
雪    币: 276
活跃值: 活跃值 (10)
能力值: ( LV9,RANK:850 )
在线值:
发帖
回帖
粉丝
大菜一号 活跃值 21 2007-6-18 10:20
3
0
你也玩这游戏的么?
雪    币: 234
活跃值: 活跃值 (11)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
ah007 活跃值 2 2007-6-18 13:06
4
0
顶一个!这个游戏我玩过。
雪    币: 209
活跃值: 活跃值 (22)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
slsdz 活跃值 2007-6-18 14:35
5
0
非常好,支持一个!
雪    币: 0
能力值: (RANK:10 )
在线值:
发帖
回帖
粉丝
LoveKuLa 活跃值 2007-6-18 14:39
6
0
真精彩。。。。。。。。
雪    币: 208
活跃值: 活跃值 (10)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
foresee 活跃值 2 2007-6-18 20:38
7
0
支持下,写的比较详细
雪    币: 200
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
ttyttyA 活跃值 2007-6-18 20:54
8
0
学习了,谢谢!
雪    币: 1876
活跃值: 活跃值 (20)
能力值: (RANK:550 )
在线值:
发帖
回帖
粉丝
hawking 活跃值 12 2007-6-18 21:39
9
0
不错,真厉害
雪    币: 202
活跃值: 活跃值 (10)
能力值: ( LV9,RANK:1130 )
在线值:
发帖
回帖
粉丝
binbinbin 活跃值 28 2007-6-19 00:05
10
0
好文,学习中~~~~~~
雪    币: 309
活跃值: 活跃值 (387)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
上网鱼 活跃值 2007-6-19 10:22
11
0
不记得当初是不是断提示框了。。。。。修改一下。。。随便点几下就全通关了。。嘿嘿。。。那是瞎搞。。。楼主纯粹技术性分析。。。。
雪    币: 200
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
panen 活跃值 2007-6-19 10:29
12
0
那个游戏确实不错。。。
雪    币: 276
活跃值: 活跃值 (10)
能力值: ( LV9,RANK:850 )
在线值:
发帖
回帖
粉丝
大菜一号 活跃值 21 2007-6-19 11:57
13
0
音乐听起来很舒服`
雪    币: 198
活跃值: 活跃值 (85)
能力值: ( LV12,RANK:2670 )
在线值:
发帖
回帖
粉丝
KuNgBiM 活跃值 66 2007-6-19 11:58
14
0
看看  学习
雪    币: 206
活跃值: 活跃值 (22)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
鸡蛋壳 活跃值 2007-6-19 16:07
15
0
去写QQ外挂还能赚点钱。
雪    币: 207
活跃值: 活跃值 (10)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
PowerBoy 活跃值 3 2007-6-19 19:29
16
0
function TSearch.CanConnect(pt1, pt2: TPoint): Boolean;
begin //判断是否可以连接(共3种情况)
  Result := CanLine(pt1, pt2) or CanLineOneCorner(pt1, pt2) or CanLineTwoCorner(pt1, pt2);
end;

function TSearch.CanLine(pt1, pt2: TPoint): Boolean;
var   //测试2点是否可以直接连接(中间无障碍)
  i: Integer;
  pt: TPoint;
begin
  Result := False;
  if pt1.X = pt2.X then
  begin
    if pt1.Y > pt2.Y then
    begin
      pt.Y := pt1.Y;
      pt1.Y := pt2.Y;
      pt2.Y := pt.Y;
    end;
    for i := pt1.Y +1 to pt2.Y -1 do
    begin
      if Maps[pt1.X,i] <> -1 then
        exit;
    end;
    Result := True;
    exit;
  end;
  if pt1.Y = pt2.Y then
  begin
    if pt1.X > pt2.X then
    begin
      pt.X := pt1.X;
      pt1.X := pt2.X;
      pt2.X := pt.X;
    end;
    for i := pt1.X +1 to pt2.X -1 do
    begin
      if Maps[i,pt2.Y] <> -1 then
        exit;
    end;
    Result := True;
    exit;
  end;
end;

function TSearch.CanLineOneCorner(pt1, pt2: TPoint): Boolean;
var   //判断2点是否由2条直线连接(一个拐点)
  pt: TPoint;
begin
  Result := False;
  pt.X := pt1.X;
  pt.Y := pt2.Y;  //拐点坐标(左下拐点)
  if (Maps[pt.X, pt.Y] = -1) and CanLine(pt,pt1) and CanLine(pt,pt2) then
  begin //
    Result := True;
    exit;
  end;
  pt.X := pt2.X;
  pt.Y := pt1.Y;  //拐点坐标(右上拐点)
  if (Maps[pt.X, pt.Y] = -1) and CanLine(pt,pt1) and CanLine(pt,pt2) then
  begin
    Result := True;
    exit;
  end;
end;

function TSearch.CanLineTwoCorner(pt1, pt2: TPoint): Boolean;
var    //判断2点是否由3条直线连接(2个拐点)
  pt: TPoint;
  i: Integer;
begin
  Result := False;
  pt.X := pt1.X;
  for i := 0 to iVCount - 1 do
  begin   //由第1个点开始向下寻找
    pt.Y := i;
    if (Maps[pt.X, pt.Y] = -1) and CanLine(pt,pt1) and CanLineOneCorner(pt,pt2) then
    begin  //如果临时点可以经过1条或者2条直线连接就TRUE
      Result := True;
      exit;
    end;
  end;
  pt.Y := pt1.Y;
  for i := 0 to iHCount - 1 do
  begin   //由第1个点开始向右寻找
    pt.X := i;
    if (Maps[pt.X, pt.Y] = -1) and CanLine(pt,pt1) and CanLineOneCorner(pt,pt2) then
    begin  //如果临时点可以经过1条或者2条直线连接就TRUE
      Result := True;
      exit;
    end;
  end;
end;

这个东西以前我好像业分析过不过分析的数据是没有了!这个是我写的东西的核心代码部分!如果有了内存地图或者是屏幕上的地图数据然后模拟左键点击,你说连连看会怎么工作啊!!!
雪    币: 276
活跃值: 活跃值 (10)
能力值: ( LV9,RANK:850 )
在线值:
发帖
回帖
粉丝
大菜一号 活跃值 21 2007-6-20 08:48
17
0
``顶楼上的!
虽然delphi代码我看不太懂~

不过饿系知道你的思路滴!
获取两图片的位置当然有多种方法`呵呵`
前提路径可通!
帮顶`
雪    币: 194
活跃值: 活跃值 (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
yosen2001 活跃值 1 2007-7-2 18:02
18
0
历害呀,支持,有水平~
雪    币: 202
活跃值: 活跃值 (15)
能力值: ( LV9,RANK:1170 )
在线值:
发帖
回帖
粉丝
bxm 活跃值 29 2007-7-3 08:08
19
0
好厉害,向牛人学习.
雪    币: 200
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
clothing 活跃值 2007-7-3 22:18
20
0
游客
登录 | 注册 方可回帖
返回