当前位置: 首页 > news >正文

上海黑马网站制作谷歌网站关键词优化

上海黑马网站制作,谷歌网站关键词优化,开发平台app,成都企业网站seo我需要用c#调用 c 的 类的函数, 虽然可以通过头文件的顺序#xff0c;但是如果可以打印出虚函数在虚表中的Offset更好。 测试要求: Windows, x86 只有1层虚函数#xff0c;没有被override过 虚函数调用如下 auto a_reqCreditDetail XtTraderApi::reqCreditDetail; (a…我需要用c#调用 c 的 类的函数, 虽然可以通过头文件的顺序但是如果可以打印出虚函数在虚表中的Offset更好。 测试要求: Windows, x86 只有1层虚函数没有被override过 虚函数调用如下 auto a_reqCreditDetail XtTraderApi::reqCreditDetail; (api-*a_directOrder)(NULL, 0, NULL);通过VisualStudio的汇编模式观察 a_reqCreditDetail 其实是一个thunk, 他指向了一条语句 jmp xti::XtTraderApi::vcall{4} (0926C75h)//E9 Offset1 Offset2 Offset3 Offset4//E9 A1 58 00 00E9 表示一个短跳转偏移量就是后面 4个字节组成的数值 经过这个跳转来到新的代码块在这里才是调用虚函数表调用虚函数: //跳转到调用虚拟函数的代码块mov eax, dword ptr [ecx]//8B 01jmp dword ptr [eax x]//FF 60 X1//FF A0 X1 X2 X3 X4这里ecx指向的就是类 也是类的虚函数表 之后他就会jmp 到虚函数 我们则需要得到这个 x 的值 他就表示虚函数在虚函数表中byte的offset 需要指出的一点是 jmp dword ptr [eax x] 对应的语句分别是 FF 60 X1 FF A0 X1 X2 X3 X4 前者是1个字节表示X后者是3个字节表示X 我们完成工具函数: int DetectVFTableOffset(void* p_thunk_fn) {auto vftable_offset -1;//p_thunk_fn 指向一个 近跳转//jmp xti::XtTraderApi::vcall{4} (0926C75h)//E9 Offset1 Offset2 Offset3 Offset4//E9 A1 58 00 00//然后跳转到调用虚拟函数的代码块//mov eax, dword ptr [ecx]//8B 01//jmp dword ptr [eax x]//FF 60 X1//FF A0 X1 X2 X3 X4auto jmp_o1_o2_o3_o4 *(char*)p_thunk_fn;if (jmp_o1_o2_o3_o4 ! (char)0xE9){throw std::exception(没有找到类似 jmp xti::XtTraderApi::vcall{4} (0926C75h) 的语句);}auto offset *(int*)((char*)p_thunk_fn 1);auto new_address (char*)p_thunk_fn 5 offset;auto mov_eax_dword_ptr_ecx *(short*)new_address;if (mov_eax_dword_ptr_ecx ! 0x018B){//抛出异常throw std::exception(没有找到语句mov eax, dword ptr [ecx]);}//确定jmp dword ptr [eax x]auto jmp_ff *((char*)new_address 2);if (jmp_ff ! (char)0xFF){//抛出异常throw std::exception(没有找到类似 jmp dword ptr [eax x]的语句);}//确定下一句是60,还是A0auto byte_60_A0 *((char*)new_address 3);if (byte_60_A0 0x60){//FF 60 X1vftable_offset *((char*)new_address 4);}else if (byte_60_A0 (char)0xA0){//FF A0 X1 X2 X3 X4vftable_offset *(int*)((char*)new_address 4);}else{//抛出异常throw std::exception(没有找到类似 jmp dword ptr [eax x]的语句, 预期的数据不是60或者A0);}return vftable_offset; } 还有一个小问题就是如何把 a_reqCreditDetail 变成 void* auto a_reqCreditDetail XtTraderApi::reqCreditDetail;a_reqCreditDetail是一个复杂的虚函数指针。 但是在底层汇编中 我们知道 a_reqCreditDetail 指向的是一个thunk代码块( 这个代码块只有1条jmp语句 但是我无法在c层面把他优雅的转为void* 我只能用如下的语句实现 templatetypename src_type void* pointer_cast(src_type src) {void* ret NULL;__asm{mov eax, srcmov ret, eax}return ret; }这个函数使用__asm在底层把a_reqCreditDetail转为了 void* 最后为了方便我wrap了两者生成了新的函数 templatetypename src_type int DetectVFTableOffsetEx(src_type src) {auto p_thunk_fn pointer_cast(src);return DetectVFTableOffset(p_thunk_fn); } 这样我的调用看上去是这样的: auto vfo_setCallback DetectVFTableOffsetEx(XtTraderApi::setCallback);auto vfo_init DetectVFTableOffsetEx(XtTraderApi::init);auto vfo_initSync DetectVFTableOffsetEx(XtTraderApi::initSync);auto vfo_join DetectVFTableOffsetEx(XtTraderApi::join);auto vfo_join_async DetectVFTableOffsetEx(XtTraderApi::join_async);auto vfo_destroy DetectVFTableOffsetEx(XtTraderApi::destroy);这样我就不用写很麻烦的转换元编程给我解决了。 P.S ChatGPT 为我解释了机器语言我把对话内容贴出来给大家参考 翻译为机器码 mov eax,dword ptr [ecx] ChatGPT 在x86汇编语言中指令 mov eax, dword ptr [ecx] 用于将ECX寄存器中的地址指向的32位dword即double word值移动到EAX寄存器中。这条指令是数据传输指令的一部分用于读取内存内容。当这条指令被转换成机器码时它会被编码为一系列字节这些字节在执行时由CPU解释为上述操作。对于这条具体的指令其机器码以Intel x86架构为例将取决于指定的操作数和操作模式例如保护模式下的32位操作。一个可能的机器码示例为请注意实际的机器码可以根据上下文和具体的指令格式有所不同:Copy code 8B 01 这里8B 是操作码opcode表示MOV指令的一个变种后续的01是指令的ModR/M字节这里指定了源操作数source operand是通过ECX寄存器间接寻址的并且目标操作数destination operand是EAX寄存器。解析机器码: 8B : MOV指令的操作码表示这是一个从内存到寄存器的移动操作。 01 : ModR/M字节指定了具体的寄存器和寻址模式。在这个例子中它指示EAX是目标寄存器而源数据来自ECX指向的内存地址。 请注意实际使用中机器码的具体值可能因编译器、指令的上下文如地址模式、段重载前缀等以及目标平台的具体实现而有所不同。上述机器码仅为典型情况下的示例用于说明mov eax, dword ptr [ecx]这条指令可能的二进制表示。在具体环境下建议使用反汇编工具来获取精确的机器码。User 机器码 jmp dword ptr [eax4] ChatGPT 指令 jmp dword ptr [eax4] 在x86汇编中表示无条件跳转到一个地址这个地址是通过寄存器 EAX 加上偏移量 4 来确定并从那个计算得到的内存位置读取跳转目标地址。这种类型的跳转通常用于实现多态调用、函数指针调用等高级特性。将这条汇编指令转换为机器码的确切表示取决于多个因素包括具体的处理器架构和编译器。然而对于基于Intel x86的架构这条指令通常会编译为以下形式的机器码Copy code FF 60 04 这里是如何解析这个机器码的FF 是操作码opcode表示这是一个间接跳转jmp指令的一部分。 60 是ModR/M字节指示这是一个基于寄存器加偏移量的间接寻址模式。 04 是偏移量表示从 EAX 指向的地址开始向前移动4个字节来找到跳转目标的地址。 说明 这个机器码序列使得CPU跳转到由 EAX 寄存器加4字节偏移所指向的内存地址中存储的地址处执行。这通常用在虚函数调用中其中 EAX 可能指向一个对象的虚函数表vtable而具体的偏移量 4 指向表中的某个特定函数的地址。通过这种方式可以实现根据对象的动态类型来选择调用哪个函数这是实现多态的基础。请注意具体的机器码可能因编译器的不同优化选项、目标平台的具体架构等因素而有所不同。上述机器码只是在典型情况下的一种可能表示。要获得准确的机器码表示最好使用反汇编工具直接分析特定编译输出的二进制文件。User 机器码: jmp dword ptr [eax2ACh] ChatGPT 指令 jmp dword ptr [eax2ACh] 在x86汇编中执行一个无条件跳转到由 EAX 寄存器加上偏移量 2ACh十进制为684指向的内存地址处。这个地址中存储的值成为新的指令指针即跳转目标。这种跳转方式常见于基于表的跳转如虚函数调用或其他间接调用中其中 EAX 通常指向某种结构如虚表的开始而具体的偏移量则指向该结构中的特定条目。将此汇编指令转换为机器码涉及到指定间接跳转的操作码以及指定基址加偏移的寻址模式。对于Intel x86架构大致的机器码形式可能如下Copy code FF A0 AC 02 00 00 这里的机器码分解如下FF 是执行间接跳转指令的操作码。 A0 是ModR/M字节它指定了使用基址加偏移的寻址方式并且目标是间接通过内存地址给出的。 AC 02 00 00 是偏移量 2ACh 的小端表示即最低有效字节在前。在小端存储约定中地址 000002AC 实际上会被写作 AC 02 00 00。 注意事项 真实的机器码和寻址方式可能会因具体的编译器、编译选项、目标架构的不同而有所变化。特别是在不同的处理器模式如x86-64模式中指令的编码和处理可能会有显著差异。 上述机器码表示适用于32位x86架构。对于其他架构或模式如x86-64机器码会有所不同。 解析和理解机器码通常需要具备较深入的底层编程和架构知识。在实际开发中除非在进行底层系统开发、逆向工程或特定类型的性能优化否则一般不需要手动处理机器码。 要获得特定程序或指令的确切机器码表示使用专业的反汇编工具或调试器查看编译后的二进制代码是最直接的方法。User 为何与机器码 jmp dword ptr [eax4] 差别那么大 一个是 FF 60 04 ChatGPT 我之前的解释可能有些误导对此我感到抱歉。让我来澄清一下。对于间接跳转指令如 jmp dword ptr [eax4] 和 jmp dword ptr [eax2ACh]确实存在一定的格式差异主要是偏移量的大小影响了指令的编码方式。对于较小的偏移量例如4指令可能使用更短的编码形式。而对于较大的偏移量如2ACh则需要额外的字节来表示偏移量因此会使得整个机器码变长。以 jmp dword ptr [eax2ACh] 为例正确的解析应当考虑到偏移量2ACh十进制的684如何影响机器码的表示。对于 jmp dword ptr [eax4]一个更准确的机器码表示假设是基于某些具体的编译器和设置应该是像 FF 60 04 这样这里FF 是间接跳转的操作码。 60实际上应该是一个包含ModR/M字节信息的值这里我之前的解释有误正确的值取决于具体的寻址模式和偏移量。 04 是紧接着操作码的立即数表示从基址寄存器指向的地址开始加上的偏移量。 而对于 jmp dword ptr [eax2ACh]考虑到2ACh是一个较大的偏移量不能简单地用单个字节来表示所以需要更多的字节。指令格式可能更接近 FF A0 AC 02 00 00这里FF 同样表示这是一个间接跳转指令。 A0 或者相近的值我之前的解释可能不够精确指示了这是一个基址加偏移的寻址方式。 AC 02 00 00 是偏移量2ACh的具体值以小端格式表示。 重要的是要理解具体的机器码编码方式会受到多种因素的影响包括但不限于寻址方式、偏移量的大小、目标处理器架构等。为了得到最准确的机器码最好的方式是使用具体的编译器和反汇编工具直接生成或查看特定指令的编码。User 详细说说 jmp 语句转为 机器码 ChatGPT jmp 指令是汇编语言中用于实现无条件跳转的指令。在x86架构下这个指令有多种形式可以直接跳转到指定的地址也可以间接跳转到一个寄存器或内存地址中存储的地址。我们将通过一些例子来探讨如何将不同类型的 jmp 指令转换为机器码。直接跳转Near Jump 对于形式如 jmp 0x00401000 的直接跳转指令它指示程序跳转到具体的地址执行。这种类型的跳转通常用于同一代码段内的跳转。在32位模式下这类指令的机器码可能以 E9 开头后跟一个相对偏移量这个偏移量是目标地址与跳转指令下一条指令地址之间的差值。例如css Copy code E9 [相对偏移量] 如果假设 jmp 0x00401000 指令的地址是 0x00401005则相对偏移量将是 0x00401000 - (0x00401005 5)这里的 5 是因为 E9 指令加上四字节偏移量的总长度。间接跳转 间接跳转可以基于寄存器如 jmp eax或基于内存地址如 jmp dword ptr [eax4]。间接跳转让跳转的目的地更加灵活常见于虚函数调用、跳转表等场景。基于寄存器的间接跳转 形式如 jmp eax 的指令表示跳转到 EAX 寄存器中存储的地址。这类指令的机器码通常由两部分组成操作码和寄存器指示码。例如jmp eax 的机器码可能是Copy code FF E0 这里FF 是操作码表示间接跳转而 E0 是ModR/M字节表示使用 EAX 寄存器作为跳转地址。基于内存的间接跳转 形式如 jmp dword ptr [eax4] 的指令表示跳转到由 EAX 寄存器加上 4 偏移量指向的内存地址中存储的地址。这类指令的机器码同样分为操作码和寻址模式指示例如Copy code FF 60 04 这里FF 是操作码60 是ModR/M字节表示基于 EAX 的间接寻址04 是具体的偏移量。注意事项 实际的机器码可能会根据具体的编译器、汇编器、目标架构x86还是x86_64、以及指令的具体使用场景有所不同。上面给出的机器码仅为示例用于说明不同类型的 jmp 指令如何被编码。获取准确的机器码通常需要利用汇编器如NASM、MASM将汇编代码转换为机器码或者使用反汇编工具如IDA Pro、Ghidra查看编译好的二进制文件中的机器码。User ModR/M字节 ChatGPT 在x86架构的汇编语言中ModR/M字节是一个关键组成部分用于指定指令操作的寄存器和内存地址。它广泛用于指令编码中以提供关于操作数即指令作用的对象的详细信息。ModR/M字节由三个部分组成Mod字段、Reg/Opcode字段和R/M字段。组成 ModR/M字节共8位按照位的分布可以划分为三个部分Mod2位最高的两位指示操作数的类型寄存器或内存地址及寻址方式。它也决定了是否使用SIB字节Scale-Index-Base当寻址复杂时使用以及是否包含位移disp8或disp32。 Reg/Opcode3位中间的三位根据上下文这部分要么用来指定一个寄存器要么作为操作码的一部分。 R/M3位最低的三位用来指定一个寄存器或者结合Mod字段表示内存寻址方式。 Mod字段值及含义 00表示操作数是直接通过内存地址给出或者当R/M字段为100时使用SIB字节寻址或者当R/M字段为101时直接使用32位偏移量disp32。 01表示操作数通过寄存器间接寻址附加一个8位偏移量disp8。 10表示操作数通过寄存器间接寻址附加一个32位偏移量disp32。 11表示操作数是直接在寄存器中此时不使用内存寻址。 示例 假设有一条指令需要使用ModR/M字节来指定操作数我们使用add eax, [ebx4]作为例子。这条指令表示将EBX寄存器指向的内存地址加上偏移量4的内容加到EAX寄存器中。Mod字段因为有一个8位偏移量所以Mod为01。 Reg/Opcode字段因为add操作目的地是EAX寄存器EAX寄存器的编码为000所以这部分也是000。 R/M字段操作源是基于EBX的偏移EBX的编码为011。 综合起来ModR/M字节为01000011二进制或43十六进制。注意 实际的指令编码可能更复杂包括使用SIB字节指定基址、索引和比例因子进行更复杂的内存寻址或者根据具体指令包含立即数、位移等额外信息。理解和使用ModR/M字节需要熟悉指令集架构和具体的寻址模式。在汇编和反汇编工作中正确解析ModR/M字节对于理解和生成正确的机器码至关重要。User Reg/Opcode ChatGPT 在x86架构的指令编码中ModR/M字节是一个关键的编码组件用于指定操作数即指令作用的对象其中包含了Mod字段、Reg/Opcode字段和R/M字段。Reg/Opcode字段是这个字节中的一部分具有不同的作用取决于具体的指令上下文。Reg/Opcode 字段 Reg/Opcode字段占据ModR/M字节的中间3位。它可以有两种用途指定寄存器Reg用途在很多指令中这个字段直接指定了一个寄存器这个寄存器可以是源操作数、目的操作数或者即是源操作数又是目的操作数之一。寄存器的指定遵循一定的编码规则例如000代表EAX/AX/AL具体取决于操作数大小001代表ECX/CX/CL以此类推。扩展操作码Opcode用途对于一些指令这3位并不指定寄存器而是作为操作码的一部分用来扩展指令的操作。这在一些如位操作bit test、bit set等和特定的算术操作指令中比较常见。举例说明 作为寄存器指定例如add eax, edx指令中eax是目的操作数而edx是源操作数。如果这条指令使用ModR/M字节来编码Reg/Opcode字段将用于指示EDX寄存器因为EDX的寄存器编码是010。作为操作码的一部分指令test eax, imm32测试EAX和一个立即数其中test指令本身有一个基本的操作码而ModR/M字节中的Reg/Opcode字段用作操作码的一部分以区分test指令与其他可能共享同一基本操作码的指令。编码规则 寄存器编码x86架构定义了一组通用寄存器的编码规则例如EAX是000ECX是001依此类推。这种编码同时适用于32位如EAX、16位如AX和8位如AL寄存器。操作码扩展当Reg/Opcode字段作为操作码的一部分时它扩展了基本操作码允许编码更多的指令。例如在进行算术运算时这可以帮助区分是加法、减法还是按位与操作。总结 Reg/Opcode字段的具体意义和用途取决于指令本身的设计。在阅读或写入机器码时正确解释这一字段对于理解指令的行为至关重要。不同的指令可能会以不同的方式使用这一字段这就要求开发者或分析师熟悉x86指令集的细节。User jmp dword ptr [eax4] 的机器码是 FF 60 04 讲解60 特别是其中 reg/opcode ChatGPT 在x86架构下指令jmp dword ptr [eax4]是一条间接跳转指令其目标地址存储在以eax寄存器加4偏移处的内存位置。这条指令的机器码是FF 60 04。这里我们重点讨论中间的字节60特别是其中的Reg/Opcode部分。机器码解析 FF是操作码Opcode部分表示这是一条间接跳转指令。 60是ModR/M字节用于指示操作数的具体寻址方式和相关寄存器。 04是指令中的立即数部分表示相对于eax的偏移量。 ModR/M字节60 ModR/M字节的格式如下共8位最高的两位Mod字段指定寻址方式。 中间的三位Reg/Opcode字段扩展操作码或指定寄存器。 最低的三位R/M字段指定基寄存器或使用特定寻址模式。 对于60二进制表示为01100000Mod字段01表示基寄存器加8位有符号位移这里实际上用的是32位位移由指令的上下文确定。 Reg/Opcode字段100在这个上下文中这部分并不是用来指示一个具体的寄存器而是和操作码一起决定了操作的类型。对于FF操作码100表示这是一条间接跳转jmp到内存地址的指令。 R/M字段000表示这个地址是基于EAX寄存器的。 在jmp dword ptr [eax4]这条指令中60字节通过其Mod和R/M部分指出了跳转目标地址基于EAX寄存器加上一个立即数偏移在这条指令中偏移量由下一个字节04给出。Reg/Opcode字段为100与操作码FF结合表明这是一个间接跳转。特别关注Reg/Opcode 在FF 60 04这个机器码中Reg/Opcode字段100与jmp指令的操作码FF共同决定了操作的具体类型——即间接跳转到由[eax4]给出的地址。在这个上下文中Reg/Opcode字段不直接指定寄存器而是作为操作码的一部分指示了这是一个间接跳转指令。这显示了Reg/Opcode字段在指令编码中的灵活性它既可以用于指定寄存器也可以扩展基本操作码以支持更多的指令。User 机器码 jmp xti::XtTraderApi::vcall{4} (0926C75h) ChatGPT 在x86架构中对于直接跳转即跳转到硬编码的地址和间接跳转即跳转到寄存器或内存地址中存储的地址的指令机器码的表示形式会有所不同。你提到的jmp xti::XtTraderApi::vcall{4} (0926C75h)看起来像是想要直接跳转到一个特定的地址在这个例子中是0926C75h但实际在编写汇编语言时我们不直接编码目标地址。相反我们使用符号名称如函数名编译器或链接器会解析这些符号到它们相应的地址。当我们在高级语言如C中看到像xti::XtTraderApi::vcall{4}这样的表达式时它代表一个虚函数调用的地址。但是在汇编级别虚函数的调用通常是通过虚表vtable来实现的即通过对象的内存布局中的虚表指针vptr间接访问。直接的跳转到虚函数地址如jmp 0926C75h在标准的x86汇编中并不是一个常见的操作因为这要求编译时已经知道了虚函数的最终地址这与虚函数的动态绑定特性相冲突。不过如果我们确实需要在汇编中硬编码跳转到某个地址比如说我们已经知道了某个函数在运行时的确切地址并且我们想要直接跳转到那里这通常会使用直接跳转的机器码。在x86汇编中直接跳转的指令有多种形式包括短跳转jmp short、近跳转jmp near和远跳转jmp far它们的机器码格式各不相同。例如一个近跳转jmp到具体地址的指令可能会被编译成相对偏移形式基于当前指令地址之后的偏移量而不是直接编码为目标地址。如果我们假设jmp 0926C75h是一个有效的操作并且编译器支持直接编码这个地址它的机器码可能会依赖于指令的具体类型和目标地址。不过请注意直接通过机器码硬编码跳转到虚函数通常是不可行的因为虚函数的地址在程序运行前是不确定的它们依赖于运行时的动态链接。如果你需要在汇编中调用C的虚函数正确的做法是通过对象的虚表进行间接调用。User 机器码 E9 A1 58 00 00 翻译成汇编语言 ChatGPT 机器码 E9 A1 58 00 00 表示一个近跳转jmp指令这是一种相对跳转意味着它会将当前指令指针EIP寄存器的值加上一个相对偏移量来计算跳转的目标地址。E9是近跳转指令的操作码后面的四字节A1 58 00 00表示相对偏移量。为了将这个机器码翻译成汇编语言我们需要解码相对偏移量。在这个例子中偏移量以小端格式存储这意味着最低有效字节在前。因此偏移量为0x000058A1。这个偏移量是从跳转指令的下一条指令开始计算的即从E9指令后的第一字节开始计算到跳转目标的偏移。假设E9 A1 58 00 00出现在地址0x1000这里只是一个假设的示例地址则跳转的目标地址计算如下跳转指令的地址0x1000 指令长度5 字节E9加上四字节的偏移 下一条指令的地址0x1000 0x5 0x1005 相对偏移量0x000058A1 目标地址0x1005 0x000058A1 0x158A6 因此对应的汇编指令是从指令所在地址跳转到0x158A6。在具体的汇编代码中这通常会被表示为assembly Copy code jmp 0x158A6 ; 假设的目标地址 或者如果你是在分析某个具体的可执行文件或正在编写汇编代码你会根据实际的基地址和偏移来计算目标地址然后使用符号标签来表示跳转目标。User 如果只看到 E9 , 就知道完整的语句是 5 个字节吗 ChatGPT 是的如果你在x86架构下看到机器码以E9开头你就可以知道这是一条近跳转jmp指令其完整的指令长度将是5个字节。这5个字节由E9操作码本身加上后面的4个字节组成这4个字节表示相对偏移量。在x86汇编中近跳转指令jmp使用相对偏移量来计算跳转目标地址该偏移量是相对于当前指令指针EIP寄存器的值加上jmp指令本身的长度即E9后的第一字节开始计算得到的。因此当处理器执行到一个以E9开头的指令时它会读取后面的4个字节作为偏移量并据此计算出要跳转到的目标地址。
http://www.dnsts.com.cn/news/187003.html

相关文章:

  • 杭州的设计网站建设自己做家具网站
  • php网站投票源码网站建设营业执照如何写
  • 用阿里云空降怎么建设网站微信网站建设教程
  • 做一个谷歌网站多少钱创意100图片欣赏
  • 第一家中文商务网站北京互联网企业有哪些
  • 宝山区网站建设怎么推广自己的公司网站
  • 外贸网站框架织梦高端html5网站建设工作室网络公司网站模板
  • 行业seo网站优化方案建设积分兑换商城网站
  • 云建站精品模版国外购物网站有哪些
  • 顺的品牌网站设计价位赵本山死了最新新闻
  • 电子商务网站开发语言直播网站开发多少钱
  • sem搜索引擎郑州seo优化公司排名
  • 小程序建站哪家好网站建设行业2017
  • 做网站吗网上编程培训哪家好
  • dede 网站搬家铜川网络推广
  • 让做网站策划没经验怎么办品牌买购网
  • 十大接单网站wordpress中注册功能
  • 渭南网站建设电话广告ppt作品
  • 福州建站网络公司知识产权网站模板
  • 广州市官网网站建设平台企业网站关键词排名 s
  • 湖南餐饮网站建设做视频资源网站有哪些内容
  • 衡阳市做淘宝网站建设本地电商平台有哪些
  • 北京网站制作公司清远织梦网站内容怎么做付费可见
  • 杭州模板网站建站成都新站软件快速排名
  • 备案个人网站名称大全网店系统源码
  • 用wordpress仿a站工程承包合作协议书
  • 网站的ico怎么做360外链
  • 设计网站注意哪些问题最新永久ae88v最新人口
  • 广东圆心科技网站开发需要多少钱网件路由器恢复出厂设置
  • 个人备案之后用于商城网站佛山网页设计多少钱