吾爱汇编

 找回密码
 立即注册

QQ登录

绑定QQ避免忘记帐号

查看: 2039|回复: 6

[转载技术] 第四十七章-Patrick的CrackMe-Part2

[复制链接]
Shark恒 发表于 2015-1-20 17:28 | 显示全部楼层 |阅读模式

                    第四十七章-Patrick的CrackMe-Part2
我们接着上一章的继续讲,上一章的结尾处我们是通过如下方式来附加新创建的进程的,首先将NTDLL.DLL中调用其他模块的入口点那一条指令设置为一个死循环,然后将OD设置为即时调试器(JIT),接着打开任务管理器,选中新创建的进程单击鼠标右键选择调试,这样OD就附加了新创建的进程。接着在死循环的指令处设置一个断点,然后将Patch过的字节码恢复为原始字节,然后直接按F9键运行两次后,模块列表窗口中就会出现AntiDebugDll.dll了,接着我们给AntiDebugDll.dll的代码段设置内存访问断点,然后删除掉之前设置的INT 3断点,运行起来,这样就可以断在AntiDebugDll.dll的入口点处了。
image002.jpg
image004.jpg
现在我们打开了两个OD,其中一个被调试的为父进程,另一个被调试的为子进程。
image006.jpg
现在父进程处于CreateProcessA调用语句的返回地址处。
image008.jpg
子进程处于AntiDebugDll.dll的入口点处。这里我将调试子进程的OD换了一种配色方案,这样可以防止大家在阅读的时候将两个OD搞混淆了。
理论上来说,现在我们需要同时模拟执行这两个进程,但实际上我们无法做到同时调试。我们只能够分别协同调试两个进程。
我们知道父进程中调用CreateMutexA这个函数,这里我们给子进程的中CreateMutexA也设置一个断点。
image010.jpg
我们运行起来,断在了这里,这里由于父进程已经创建了MYFIRSTINSTANCE这个互斥体,所以我们如果执行了该函数,GetLastError的错误码将返回0xB7,即ERROR_ALREADY_EXISTS。这里我们执行到返回验证一下。
image012.jpg
这里我们可以看到LastErr为ERROR_ALREADY_EXISTS,即0xB7。表示互斥体已经存在。
image014.jpg
接着这里调用RtlGetLastWin32Error获取错误码,这里错误码我们已经知道了是0xB7了,即ERROR_ALREADY_EXISTS。
image016.jpg
image018.jpg
这里将错误码保存到10010ECC指向的内存单元中,我们给该内存单元设置一个内存访问断点,运行起来。
断在了这里,这里是读取该错误码进行比较。
image020.jpg
这里将RtlGetLastWin32Error返回的错误码与0xB7做比较。
接着如果相等的话,通过SETE指令将EAX置1,这里明显错误码等于0xB7,所以EAX被置1,如果是父进程的话,EAX会被置0。
image022.jpg
接着我们返回到了这里,子进程中1000262C这处条件跳转将成立,而父进程此处跳转将不会成立。所以之后父进程与子进程将执行不同的分支流程,有待我们进一步分析。
这里有没有觉得这样一点点单步跟踪有点麻烦?
其实有网上很多好用的API监视工具,比如说KAM,APISPY,这些工具可以记录程序中执行了哪些API函数,不需要我们一步步的跟踪,可以节省很多时间。
这里其实我们可以利用内存访问断点间接的完成API函数的监视工作,不需要这样一步步单步跟踪。具体操作如下:
首先我们需要定位子进程中AntiDebugDll.dll这个模块的IAT,这里我们将反汇编窗口往上拉,随便找一个API函数调用处。
image024.jpg
我们可以看到100024B5处调用了WideCharToMultiByte这个API函数,该API函数的指针位于1000C034地址处,它是AntiDebugDll.dll的IAT中的一项。我们在数据窗口中定位到该IAT项。
image026.jpg
这里就是IAT了,我们定位到该IAT的起始位置和结束位置,然后选中整个IAT,单击鼠标右键选择Breakpoint-Memory,on access,给整个IAT设置内存访问断点。
image028.jpg
接下来我们同样给父进程的AntiDebugDll.dll的整个IAT表设置内存访问断点。
image030.jpg
这里我们就给父子进程的AntiDebugDll.dll的IAT都设置了内存访问断点,也就说当程序中调用AntiDebugDll.dll模块IAT中的API函数时就会断下来,这里还需要注意一点,有可能该Dll会通过调用GetProcAddress来获取其他的API函数指针,所以这里我们给GetProcAddress也设置一个断点,以防万一。
好了,现在我们继续调试子进程,我们按F9键运行起来,看看调用哪些API函数。
image032.jpg
断在了这里,这里要创建MYMAININSTANCE这个互斥体,这个互斥体之前未被创建过。
image034.jpg
大家应该还记得之前父进程创建的那个互斥体吧,叫做MYFIRSTINSTANCE,顾名思义:”第一个实例”。
这里要创建的互斥体叫做MYMAININSTANCE。顾名思义:”主体实例”。
我们按F8键执行该API函数。
image036.jpg
这里我们可以看到错误码为ERROR_SUCCESS,说明互斥体创建成功。
好,我们按F9键运行起来,看看下面会调用哪个API函数。
image038.jpg
这里又是调用RtlGetLastWin32Error获取上次调用CreateMutexA这个API函数的错误码,我们继续按F9键运行。
image040.jpg
这里是获取进程句柄,我们按F8键执行调用API函数,会返回(-1)FFFFFFFF。代表当前进程。该句柄不在句柄表中,不是真正的句柄,我们叫它伪句柄。
image042.jpg
继续按F9键运行。
image044.jpg
这里调用的是GetModuleHandleA,这样的跟踪对于我们练习哪些不熟悉的API函数是一种极佳的锻炼。我们按F8键执行。
image046.jpg
这里返回的是NTDLL.DLL这个模块的句柄。我猜测该程序会用该句柄作为GetProcessAddress的参数来获取NTDLL.DLL中包含的API函数指针。
image048.jpg
我希望我猜测是正确的,我们按F9键运行起来。
image050.jpg
嘿嘿,看来我们的猜测是正确的。
我们来看看其参数。
image052.jpg
这里可以看到其要获取DbgUiRemoteBreakin这个API函数的指针。我们继续F9运行。
image054.jpg
image056.jpg
这里我们可以看出一点该程序的意图了,它想通过Patch DbgUiRemoteBreakin这个函数的实现代码来达到反调试的目的。这里是修改DbgUiRemoteBreanin这个API函数首字节的访问属性,将访问属性修改为可读可写可执行。
image058.jpg
这里要调用WriteProcessMemory开始修改DbgUiRemoteBreakin的首字节了,我们来看看参数。
image060.jpg
这里我们可以看到进程句柄为FFFFFFFF,也就是当前进程,通过之前那个GetCurrentProcess获取到的。
这里我们来看看DbgUiRemoteBreakin的实现代码。
image062.jpg
这里我们可以看到DbgUiRemoteBreakin中会调用DbgBreakPoint,我们执行该API函数看看其将DbgUiRemoteBreakin的首字节修改为了什么。
image064.jpg
这里我们可以看到DbgUiRemoteBreakin的首字节被修改为了RET指令。
我们继续运行。
image066.jpg
这里又是获取NTDLL.DLL的模块句柄,接着调用GetProcAddress获取DbgBreakPoint的函数指针,接着Patch之。
image068.jpg
image070.jpg
修改DbgBreakPoint首字节的访问权限。
image072.jpg
这里要Patch DbgBreakPoint首字节了,我们来看看参数。
image074.jpg
这里我们来看看DbgBreakPoint的实现代码。
image076.jpg
我们按F8键执行,看看DbgBreakPoint的首字节被修改为了什么。
image078.jpg
这里我们可以看到DbgBreakPoint的首字节被修改为了RET。这样也可以达到反调试的目的。我们继续F9运行。
image080.jpg
这里调用OpenMutexA这个API函数,打开名为WAIT的互斥体,大家应该还记得父进程已经创建了一个名为WAIT的互斥体吧,
我们打开父进程所在OD的句柄列表窗口看看。
image082.jpg
我们可以看到父进程中的确存在一个WAIT的互斥体,这里子进程中并没有调用CreateMutexA,而是调用OpenMutexA来打开这个互斥体,这里可以顺利获取到之前父进程中创建的WAIT互斥体的句柄。
image084.jpg
我们按F8键执行该函数,可以看到成功获取到了WAIT互斥体的句柄,为0x54。
image086.jpg
现在我们来看看子进程所在OD的句柄列表窗口。
恩,成功打开了WAIT这个互斥体。
我们继续F9键运行。
image088.jpg
这里我们可以看到调用WaitForSingleObject这个函数进行父进程与子进程的同步处理。我们来看看其参数。
image090.jpg
这里第一个参数为WAIT这个互斥体的句柄,第二个参数为5000ms,即超时时间为5秒钟。也就是说子进程会等待父进程释放WAIT互斥体的信号量,如果超过5秒父进程还没有释放该函数就直接返回。
下面一条语句将WaitForSingleObject的返回值保存到变量中。
image092.jpg
image094.jpg
这里我们可以看到将WaitForSingleObject的返回值与零进行比较,如果等于零(即WAIT_OBJECT_0:成功等到信号量释放)就可以绕过下面的ExitProcess的调用处。
image096.jpg
image098.jpg
这里为了让子进程不因为WaitForSingleObject等待超时而退出,我们将WaitForSingleObject的超时时间修改为INFINITE(无穷大)。
image100.jpg
这里我们将WaitForSingleObject的第二个参数由0x1388修改为了FFFFFFFF(-1),即INFINITE。这里为了让父进程释放WAIT互斥体信号量的时候我们能够子进程能够顺利断下,我们给下一条指令处设置一个断点。
image102.jpg
按F9键运行起来。
image104.jpg
现在我们可以看到子进程已经运行起来了。也就是说子进程正在等待父进程释放WAIT这个互斥体的信号量。由于子进程所在OD的右下方现在显示的是Running状态,所以现在我们不能调试子进程了。转而我们现在来调试父进程。
大家应该还记得子进程中的WaitForSingleObject的超时时间为5秒吧?如果是5秒的话,那么子进程过了5秒,父进程还没有释放WAIT信号量,子进程就会调用ExitProcess退出了。所以我们将超时时间修改为了FFFFFFFF(即INFINITE),那么子进程只能乖乖的一直等待,直到父进程释放WAIT信号量为止,嘿嘿。
现在我们来调试父进程,我们已经对父进程中AntiDebugDll.dll模块的整个IAT设置内存访问断点了,所以我们直接运行起来,看看会调用哪些API函数。
image106.jpg
我们可以看到这里调用Sleep休眠片刻,我们继续F9运行起来,看看还会调用其他的什么重要的API函数。
image108.jpg
如果断在不是很重要的API函数处的话,我们继续运行。
我们可以看到这里调用CreateFileA打开文件,有点可疑。我们来看看其参数。
这里调用CreateFileA要打开AntiDebugDll.dll,很可能要检测AntiDebugDll.dll中的代码是否被修改,防止被下INT 3断点。所以我们这里我们将之前设置的INT 3都删除掉。
image110.jpg
这里我们将断点列表窗口中的断点都删除掉。
下面我们就不设置INT 3断点了,如果实在需要设置断点,我们就用内存断点替代。
我们来看CreateFileA的参数情况:
image112.jpg
这里明显这个程序想通过CreateFileA打开AntiDebugDll.dll,然后通过ReadFile读取相应字节码进行比较,看看是否被修改。这里我们并没有修改Dll文件中的内容,我们修改的都是内存中的内容。
继续看其他参数。
image114.jpg
这里大部分参数我们都不是很关系,我们只需要注意一下dwShareMode这个参数,共享模式为FILE_SHARE_READ,我们来看一下MSDN中的解释。
image116.jpg
如果是读取操作的话,会返回成功。
我们按F8键执行,可以看到返回的句柄值。
image118.jpg
这里打开的AntiDebugDll.dll的文件句柄为0x58。我们继续执行,看看还会调用什么API函数。
image120.jpg
这里调用的是CreateFileMappingA这个API函数,创建一个文件映射。
image122.jpg
接着这里调用MapViewOfFile将文件的内容映射到内存中,我们按F8键执行该函数,看看被映射的地址是多少。
image124.jpg
这里AntiDebugDll.dll就被映射到了内存中,起始地址为9F0000,接着它将会怎么做呢?将所有的字节都逐一比较吗?不,它没有,它仅仅只比较了起始的几个字节。我们在数据窗口中定位到9F0000地址处。
image126.jpg
而我们当前正在运行的AntiDebugDll.dll的基地址为10000000,我们再到数据窗口中定位到该地址,我们可以看到两者的内容是一致的。
image128.jpg
我们继续F9键运行。
image130.jpg
这里是读取DLL文件的大小然后校验,下面接着判断文件扩展名是否为,DLL,dll,EXE,exe。
image132.jpg
继续:
image134.jpg
删除9F0000地址处的内存映射,说明不再需要这些字节了。
image136.jpg
关闭掉文件句柄。
image138.jpg
这里又调用了CreateFileA,参数如下:
image140.jpg
dwDesiredAccess的值为GENERIC_READ,但是dwShareMode的值被设置为了0。MSDN中的解释是如果dwShareMode被设置为零,该句柄不共享,再关闭之前不能被再次打开。这里如果我们按F8键执行的话,将打开文件失败。EAX返回-1(即FFFFFFFF)。
image142.jpg
这里我们可以看到返回的句柄为FFFFFFFF,即打开文件失败,LastErr为ERROR_SHARING_VIOLATION。
image144.jpg
继续。我们可以看到下面这部分代码,如果刚刚读取文件打开文件成功的话,那么接着将读取文件成功。接着这里会对读取到的文件内容进行处理,有可能是解密代码哟!下面10003901地址处调用的10005010是解密的核心部分。
image146.jpg
这里刚刚由于打开文件失败,所以并不会执行刚刚解密操作,这里我们需要重来一遍前面的步骤,回到刚刚CreateFileA处。
image148.jpg
我们将dwShareMode修改为FILE_SHARE_READ,即1,让打开文件成功。接下来会读取文件,然后对读取到的文件内容进行相应的处理,我们来看看对文件内容处理以后后续流程会有什么影响。
image150.jpg
按F8键执行。
image152.jpg
这里获取到了句柄,我们继续。
image154.jpg
又是ReadFile,按F8键。
image156.jpg
这里EAX返回1,接下来会对读取到的文件内容进行相应的处理,很可能是解密处理。
image158.jpg
我们继续按F9键运行。
image160.jpg
关闭句柄。
这里又到了CreateFileA处。
image162.jpg
我们会发现该程序多次调用CreateFileA,但是要注意了,这里要打开的Patrick.exe这个文件。
image164.jpg
image166.jpg
这里由于是第一次打开,所以成功获取到了文件句柄。
image168.jpg
现在又要对Patrick.exe创建文件映射了,跟之前AntiDebugDll.dll的类似。
image170.jpg
创建内存映射,映射到了AF0000这个地址处。
image172.jpg
这里我们在数据窗口中定位AF0000地址处,可以看到Patrick.exe的PE头部情况。
image174.jpg
我们再在数据窗口中定位当前程序的基地址400000。
image176.jpg
我们可以看到内容是一致的。我们按F9键继续运行。
image178.jpg
判断文件扩展名。
image180.jpg
删除内存映射,貌似没有做文件内容的检测呀。
image182.jpg
这里经过了几个不重要的API函数以后到了这里,这里要修改起始地址401000内存单元的访问权限。
image184.jpg
这里我们可以看到是要修改子进程的401000地址处的访问权限。
image186.jpg
这里调用ReadProcessMemory读取进程内容。
image188.jpg
这里我们可以看到是读取起始地址为401000,长度为16个字节的内容。
image190.jpg
image192.jpg
image194.jpg
起始地址为401000的这个区段是主程序的代码段。
我们先在来看看401000地址处的代码。
image196.jpg
明显经过加密处理了。
这里在循环调用WriteProcessMemory,写入主程序的整个代码段,我们得一直按F9键运行,直到循环结束为止。
写入整个代码段,貌似像是在解密区段的样子。继续。
image198.jpg
这里马上循环写入快结束了。
image200.jpg
这里是释放WAIT互斥体信号量,也就是子进程调用WaitForSingleObject正在等待的信号量。
image202.jpg
image204.jpg
现在我们按F8键,子进程就会运行起来。我们直接按F9键运行。
image206.jpg
这里调用的是WaitForInputIdle这个函数,我们来看看MSDN中的说明。
image208.jpg
我们可以看到该函数可以使一个线程挂起,直到规定线程初始化完成为止。对于父子进程之间的同步极为有用。
我们直接对下一条指令处设置一个断点,然后运行起来。
image210.jpg
image212.jpg
我们可以看到父进程现在已经处于运行状态了,我们现在接着来看子进程。
image214.jpg
现在子进程调用ReleaseMutex释放WAIT互斥体的信号量,但是父进程并没有调用WaitForSingleObject进行WAIT信号量的等待,所以我们继续跟踪子进程,继续按F9键运行。
image216.jpg
这里又是跟父进程一样检查AntiDebugDll.dll文件。不再赘述。
image218.jpg
image220.jpg
image222.jpg
image224.jpg
image226.jpg
现在到了关键部位了。
image228.jpg
image230.jpg
跟之前一样我们将dwShareMode修改为1。
image232.jpg
成功返回句柄。
image234.jpg
期间又调用了几个不重要的API,然后就到了ReadFile这里,读取起始的几个字节判断有没有被修改。
image236.jpg
接着这里关闭文件句柄。
image238.jpg
这里再次调用CreateFileA打开Patrick.exe。
image240.jpg
成功返回句柄。
image242.jpg
这部分与父进程是一样的,我们不再赘述。
image244.jpg
image246.jpg
image248.jpg
这里我们依然将dwShareMode修改为1。
image250.jpg
我们继续按F9键运行,经过几个API函数以后会再次调用ReadFile,读取并检测起始的几个字节内容。
image252.jpg
image254.jpg
这里这些步骤都是相似的,我们只要遇到CreateFileA,将dwShareMode修改为1即可。
image256.jpg
又是调用ReadFile进行检查。
image258.jpg
继续往下跟,这里调用GetCurrentProcess,获取当前进程的句柄,貌似要进行一些新的处理了,我们一起来看看。
image260.jpg
image262.jpg
这里又是跟父进程一样调用VirtualProtectEx修改内存访问权限,为下一步调用ReadProcessMemory,WriteProcesMemory读写内存做铺垫。
image264.jpg
接着又是WriteProcessMemory。
image266.jpg
这里又是写入起始地址为401000,长度为16的内容。
image268.jpg
我们定位到401000看看。
image270.jpg
image272.jpg
这里又是循环写入,我们一直按F9键,直到整个主程序代码段都被写完毕为止。
好,现在已经循环写入完毕了,通过PEEditor可以得知主程序的OEP为1D55,我们现在来看看401D55处的内容是什么。
可能看到的确像是入口点的样子,说明之前循环写入的确是在解密主程序代码段。
image274.jpg
image276.jpg
现在区段已经解密完毕了,接着这里要调用CreateThread创建线程,我们将CreationFlags修改为4,即挂起状态。
image278.jpg
我们定位该线程的起始地址看看,这是是创建的第一个线程,我们继续往下看,看看会不会再创建其他进程。
image280.jpg
这里是创建第二个线程,我们依然将dwCreationFlags修改为0x4。
image282.jpg
好了,现在区段已经解密完毕了,我们接下来需要顺利断在OEP处,我们直接删除之前设置的内存访问断点,然后对主程序代码段设置内存访问断点。接着运行起来。
image284.jpg
现在我们将成功断在了OEP处,下面我们来进行dump。
现在我们再打开一个OD,加载Patrick.exe,断在了系统断点处。
image286.jpg
现在我们将子进程代码段的所有字节都拷贝到这个新开的OD中。
image288.jpg
接着将修改保存到文件,我们来看下IAT,IAT项都是正常的。
现在我们就不需要执行AntiDebugDll.dll这个反调试模块中的内容了,所以我们可以直接将AntiDebugDll.dll的入口点处的指令修改为RET。
我们再次用OD加载刚刚保存的文件,断在了系统断点处,这里我们定位到AntiDebugDll.dll的入口地址:100064D4,直接将第一条指令修改为RET,让其返回。接着保存修改到文件。
image290.jpg
接着我们打开PEEditor程序的所有区段访问权限都修改为E0000020(可读可写可执行)。
这里我们还可以看到一个主程序代码段中还有一处CALL是指向的AntiDebugDll.dll的,我们直接把它NOP掉。
image292.jpg
我们保存修改到文件,直接运行修改好的CrackMe。
image294.jpg
我们现在运行起来了,我们可以看到程序正常运行。
下面我们需要进一步干掉这个AntiDebugDll.dll这个模块,让主程序无需加载这个DLL。
为了DLL不加载,我们应该进行如下处理:
image296.jpg
我们定位到导入表(IT)的起始地址为406F3C。
image298.jpg
大家应该可以记得吧,每个DLL项占5个DWORD,第4个DWORD为DLL名称字符串指针。
image300.jpg
这里第一个DLL名称字符串指针为40712E,我们一起来看一看。
image302.jpg
是WINMM.DLL,第二个DLL为AntiDebugDll.dll,这里我们为了剔除掉AntiDebugDll.dll这个模块,我们可以将AntiDebugDll.dll对应的DLL项修改得与WINMM.DLL这一个DLL项一致。
image304.jpg
保存修改到文件。
我们重启OD,再来看看导入表。
image306.jpg
如下:
image308.jpg
现在我们会发现并没有加载AntiDebugDll.dll了。
image310.jpg
image312.jpg
好了,程序完美运行。
嘿嘿,这个CrackMe我们就搞定了。

本系列文章汉化版转载看雪论坛

感谢原作者:RicardoNarvaja(西班牙人)
原作者个人主页:http://www.ricardonarvaja.info/

感谢热心翻译的朋友:
1~3章译者:BGCoder
4~58章译者:安于此生

全集配套程序下载地址:

链接: http://pan.baidu.com/s/1eQzTWfo 密码: vytv




评分

参与人数 11HB +8 THX +6 收起 理由
花盗睡鼠 + 2 + 1 [吾爱汇编论坛52HB.COM]-学破解防破解,知进攻懂防守!
虚心学习 + 1 [吾爱汇编论坛52HB.COM]-软件反汇编逆向分析,软件安全必不可少!
Jawon + 2
琉璃天空 + 1
一路走来不容易 + 1
Soul1999 + 1
消逝的过去 + 1
l278785481 + 1
hackysh + 1
hnymsh + 1
lies + 1

查看全部评分

吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
hackysh 发表于 2022-2-8 17:53 | 显示全部楼层
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
头像被屏蔽
别管我了行 发表于 2022-3-3 04:26 | 显示全部楼层

提示: 作者被禁止或删除 内容自动屏蔽
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
曾经沧海 发表于 2022-10-31 20:06 | 显示全部楼层
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
一生逍遥 发表于 2022-12-5 08:03 | 显示全部楼层

支持楼主   来学习学习下!
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
曾经沧海 发表于 2023-4-5 23:27 | 显示全部楼层
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
一生逍遥 发表于 2023-4-22 17:22 | 显示全部楼层

谢谢你  好东西 支持你!
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

警告:本站严惩灌水回复,尊重自己从尊重他人开始!

1层
2层
3层
4层
5层
6层
7层

免责声明

吾爱汇编(www.52hb.com)所讨论的技术及相关工具仅限用于研究学习,皆在提高软件产品的安全性,严禁用于不良动机。任何个人、团体、组织不得将其用于非法目的,否则,一切后果自行承担。吾爱汇编不承担任何因为技术滥用所产生的连带责任。吾爱汇编内容源于网络,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑中彻底删除。如有侵权请邮件或微信与我们联系处理。

站长邮箱:SharkHeng@sina.com
站长QQ:1140549900


QQ|RSS|手机版|小黑屋|帮助|吾爱汇编 ( 京公网安备11011502005403号 , 京ICP备20003498号-6 )|网站地图

Powered by Discuz!

吾爱汇编 www.52hb.com

快速回复 返回顶部 返回列表