Conscience Discovery has made up for the wp in the trial hundreds of years ago. After all, there is a misc in the warm-up game
Put a warehouse portal: SCNU sloth / hsctf-2021-trial: topics and wp of 2021 trial of iscnu x sloth network security research group
Misc
Where is my fufu?
Picture name Fu Fu Png indicates that there are two fufu in this picture, and it is necessary to disassemble the merged objects of this picture. Moreover, Hint also mentions that binwalk is not omnipotent. You can try binwalk. Although you can scan it, you -e can't tell it (binwalk - the conventional routine of picture steganography)
So use another split software foremost (often used in hardware
You can find two pictures in output/png:
Then there is a hint that it is two identical pictures (wife). At this time, we should try blind watermarking.
(note that there are many different versions of blind watermark. If one cannot be disassembled, you can try more. After all, you don't know which one is used by the author)
The blind watermark here uses chishaxie/BlindWaterMark: blind watermark by python , you can use this script to solve it directly:
flag: flag{T0ver_sto1e_my_FUFU_-TAT-}
Reverse
Guess
The main difficulty of the check-in problem is estimated to be the removal of flower instructions.
The function here is not recognized correctly. Just jump over and turn the function again (press u to delete this section of undefined, and then re p generate the function)
Press c to turn the code manually if it is not recognized below
Then decompile the sub_11C9(), you can see that the last is the end of puts. The guess is just a confused output, which has nothing to do with the program logic.
There are two classic call $+5 fancy instructions on the main function, which are RE routine - about reverse frequent flyer instruction | c10udlnk_Log There is parsing in, which is actually equivalent to nop (empty instruction) of the same length
Then the main function logic can be obtained by converting the function:
loc_1232 is also unrecognized and needs to jump over for conversion.
Can be transferred to:
A printf is useless (it is estimated that the printed information is a prompt)
So, in fact, let the input s satisfy (dword_4020[i] ^ s[i]) == dword_4040[i]
Write wp:
dst = [0x22, 0x5F, 0x43, 0x76, 0x2E, 0x34, 0x5C, 0x56, 0x07, 0x21, 0x37, 0x5C, 0x28, 0x15, 0x3A, 0x1B, 0xFE, 0x12, 0x01, 0x30, 0xED, 0xE9, 0x15, 0x0A, 0x65, 0xB8, 0xF5, 0x77, 0x00, 0x00, 0x00, 0x00] arr = [0x44, 0x33, 0x22, 0x11, 0x55, 0x44, 0x33, 0x22, 0x66, 0x55, 0x44, 0x33, 0x77, 0x66, 0x55, 0x44, 0x88, 0x77, 0x66, 0x55, 0x99, 0x88, 0x77, 0x66, 0x00, 0x99, 0x88, 0x77, 0x00, 0x00, 0x00, 0x00] flag = "" for i in range(len(dst)): flag += chr(dst[i]^arr[i]) print(flag)
flag: flag{potatso_so_vegetable!}
ezMath
Drag it into ida and find it strange. You can use shell checking software such as ExEinfoPE to see the upx shell.
With upx version 3.94, it can be shelled directly (Magic). In the higher version, l will be reported because the magic byte is changed by the person who created the title (that is, me)_ Info error(
Through this article article You can know l_info is actually the previous header (different versions of upx have different offset s)
Normally, a UPX shelled file will appear magic bytes three times (UPX! Or YTS\x99 modified by magic in that article, as shown in the figure below), once in the head and twice in the tail.
It can be seen that the third and fourth byte after the magic byte in the head is 0D 0C, and the two bytes immediately following the last magic byte in the tail are also 0D 0C. In fact, these two bytes indicate that the version is related (don't worry about hhh, it's right at this position anyway).
So by analogy, you can find out where the magic of the file header should be:
Therefore, part 06 22 11 03 should be UPX! (a small colored egg is buried here. Hey, dddd)
So change this to UPX! You can shell normally~
After shelling, we began to analyze and found that this is a simple interaction. We need to answer all the answers of the formula. After all the answers are correct, we can get the flag.
However, you have to answer 0xDEAD times, so it must not be a hand answer (more than 50000 times)
There are two ideas. One is to write an automatic interactive calculation program in Python, and then press and run to simulate the hand answer:
from pwn import * from hashlib import md5 # context.log_level = 'debug' r = process("./ezMath") end = 'Congratulations!' flag = '' r.readline() r.readline() r.readline() while True: cal = r.readline() if cal[:len(end)] == end: print(cal) break ans = str(eval(cal)) flag += ans r.sendline(ans) if r.readline() != 'OK! \n': print("???") print("flag{" + md5(flag.encode()).hexdigest() + "}") r.interactive()
The title is also written. Finally, the flag is handed over to md5
So you can run out of the flag in more than ten seconds:
The second is to simulate the logic of program execution, and calculate all the answers manually. After all, the seeds of random numbers are given. Just cv reproduce the code in ida:
#include <stdio.h> #include <stdlib.h> int main(int argc, const char **argv, const char **envp) { int v3; // eax int v4; // er8 int v5; // er9 int v6; // ecx int v7; // er8 int v8; // er9 int v9; // edx int v10; // ecx int v11; // er8 int v12; // er9 char v14; // [rsp+0h] [rbp-30h] char v15; // [rsp+0h] [rbp-30h] int v16; // [rsp+8h] [rbp-28h] BYREF int i; // [rsp+Ch] [rbp-24h] int v18; // [rsp+10h] [rbp-20h] int j; // [rsp+14h] [rbp-1Ch] int v20; // [rsp+18h] [rbp-18h] int v21; // [rsp+1Ch] [rbp-14h] int v22; // [rsp+20h] [rbp-10h] char v23[2]; // [rsp+26h] [rbp-Ah] // unsigned __int64 v24; // [rsp+28h] [rbp-8h] // v24 = __readfsqword(0x28u); srandom(8225); v23[0] = 43; v23[1] = 45; // puts("Welcome to EZest RE in the world!!! 0v0"); // puts("Please answer all the math probs~"); // puts("READY...?"); for ( i = 0; i <= 57004; ++i ) { v3 = rand(); v20 = v3 % 21 + 1; v18 = 2021; // printf((unsigned int)"2021", (_DWORD)argv, v3 % 21, v3 % 21, v4, v5, v14); for ( j = 0; j < v20; ++j ) { v21 = (int)rand() % 21; v22 = rand() & 1; // v22 = (unsigned __int8)v22; // printf((unsigned int)" %c %d", v23[(unsigned __int8)v22], v21, v6, v7, v8, v15); if ( v22 ) { if ( v22 == 1 ) v18 -= v21; else puts("Are you serious? "); } else { v18 += v21; } } printf("%d", v18); // putchar(10LL); // argv = (const char **)&v16; // _isoc99_scanf((unsigned int)"%d", (unsigned int)&v16, v9, v10, v11, v12, v15); // if ( v18 != v16 ) // { // puts("Try again and try again~ "); // return 0; // } // puts("OK! "); } // puts("Congratulations! Get your flag as \"flag{\"+md5(str(answer1)+str(answer2)+...).hexdigest()+\"}\""); return 0; }
Then save the results to exp2 Txt, and finally md5 operate all the answers:
from hashlib import md5 with open('exp2.txt', 'r') as f: ans = f.read().strip() print("flag{" + md5(ans.encode()).hexdigest() + "}")
flag: flag{474a444e5d6cb14261e8408e891ac1b8}
babyvm
Ah ~ VM has worked hard, and the people who have worked out the questions and the players are tired. The flag is still so great (Research pull hatred). As a result, no one has made a great success in TAT (anti AK)
There's nothing to say. Just reverse it. Remember the function of each opcode and write a parser. It's ok (I didn't go to the symbol table, but I'm merciful 555)
The rest is to see the assembly = v=
Parser:
ins_set={ 0x00:[1,0,"exit"], 0x01:[3,2,"mov r{0},0x{1:0>2X}"], 0x11:[3,2,"mov r{0},r{1}"], 0x21:[3,2,"mov [r{0}],0x{1:0>2X}"], 0x31:[3,2,"mov [r{0}],r{1}"], 0x02:[2,1,"inc r{0}"], 0x03:[2,1,"push r{0}"], 0x04:[2,1,"pop r{0}"], 0x05:[2,1,"r{0} = getchar()"], 0x06:[2,1,"putchar(r{0})"], 0x07:[3,2,"cmp r{0},0x{1:0>2X}"], 0x17:[3,2,"cmp [r{0}],[r{1}]"], 0x08:[2,1,"jnz {0:0>4}"], 0x18:[2,1,"jmp {0:0>4}"], 0x09:[3,2,"xor [r{0}],0x{1:0>2X}"], 0x19:[3,2,"xor [r{0}],r{1}"], 0x0A:[3,2,"add [r{0}],0x{1:0>2X}"], 0x0B:[3,2,"sub r{0},0x{1:0>2X}"], } opcode=\ [0x01, 0x01, 0x00, 0x21, 0x01, 0x0A, 0x02, 0x01, 0x21, 0x01, 0x01, 0x02, 0x01, 0x21, 0x01, 0x0F, 0x02, 0x01, 0x21, 0x01, 0x08, 0x02, 0x01, 0x21, 0x01, 0x13, 0x02, 0x01, 0x21, 0x01, 0x7D, 0x02, 0x01, 0x21, 0x01, 0x5A, 0x02, 0x01, 0x21, 0x01, 0x1D, 0x02, 0x01, 0x21, 0x01, 0x01, 0x02, 0x01, 0x21, 0x01, 0x17, 0x02, 0x01, 0x21, 0x01, 0x79, 0x02, 0x01, 0x21, 0x01, 0x56, 0x02, 0x01, 0x21, 0x01, 0x13, 0x02, 0x01, 0x21, 0x01, 0x7E, 0x02, 0x01, 0x21, 0x01, 0x0F, 0x02, 0x01, 0x21, 0x01, 0x1A, 0x02, 0x01, 0x21, 0x01, 0x63, 0x02, 0x01, 0x21, 0x01, 0x1F, 0x02, 0x01, 0x21, 0x01, 0x11, 0x02, 0x01, 0x21, 0x01, 0x06, 0x02, 0x01, 0x21, 0x01, 0x1E, 0x02, 0x01, 0x21, 0x01, 0x0B, 0x02, 0x01, 0x21, 0x01, 0x13, 0x02, 0x01, 0x21, 0x01, 0x48, 0x02, 0x01, 0x21, 0x01, 0x1A, 0x02, 0x01, 0x21, 0x01, 0x11, 0x02, 0x01, 0x21, 0x01, 0x69, 0x02, 0x01, 0x21, 0x01, 0x1F, 0x02, 0x01, 0x21, 0x01, 0x44, 0x02, 0x01, 0x21, 0x01, 0x19, 0x02, 0x01, 0x21, 0x01, 0x13, 0x02, 0x01, 0x21, 0x01, 0x0E, 0x02, 0x01, 0x01, 0x01, 0x57, 0x06, 0x01, 0x01, 0x01, 0x68, 0x06, 0x01, 0x01, 0x01, 0x61, 0x06, 0x01, 0x01, 0x01, 0x74, 0x06, 0x01, 0x01, 0x01, 0x20, 0x06, 0x01, 0x01, 0x01, 0x69, 0x06, 0x01, 0x01, 0x01, 0x73, 0x06, 0x01, 0x01, 0x01, 0x20, 0x06, 0x01, 0x01, 0x01, 0x79, 0x06, 0x01, 0x01, 0x01, 0x6F, 0x06, 0x01, 0x01, 0x01, 0x75, 0x06, 0x01, 0x01, 0x01, 0x72, 0x06, 0x01, 0x01, 0x01, 0x20, 0x06, 0x01, 0x01, 0x01, 0x66, 0x06, 0x01, 0x01, 0x01, 0x6C, 0x06, 0x01, 0x01, 0x01, 0x61, 0x06, 0x01, 0x01, 0x01, 0x67, 0x06, 0x01, 0x01, 0x01, 0x3F, 0x06, 0x01, 0x01, 0x01, 0x0A, 0x06, 0x01, 0x01, 0x01, 0x00, 0x05, 0x02, 0x03, 0x02, 0x02, 0x01, 0x07, 0x01, 0x20, 0x08, 0xF5, 0x01, 0x01, 0x00, 0x0A, 0x01, 0x40, 0x02, 0x01, 0x07, 0x01, 0x20, 0x08, 0xF6, 0x01, 0x01, 0x40, 0x04, 0x02, 0x0B, 0x01, 0x01, 0x31, 0x01, 0x02, 0x07, 0x01, 0x20, 0x08, 0xF3, 0x01, 0x01, 0x20, 0x11, 0x02, 0x01, 0x0B, 0x02, 0x20, 0x19, 0x01, 0x02, 0x02, 0x01, 0x07, 0x01, 0x40, 0x08, 0xF0, 0x01, 0x01, 0x20, 0x0A, 0x01, 0x20, 0x02, 0x01, 0x07, 0x01, 0x40, 0x08, 0xF6, 0x01, 0x01, 0x00, 0x01, 0x02, 0x20, 0x09, 0x01, 0xCC, 0x17, 0x01, 0x02, 0x08, 0x2E, 0x02, 0x01, 0x02, 0x02, 0x07, 0x01, 0x20, 0x08, 0xEF, 0x01, 0x01, 0x52, 0x06, 0x01, 0x01, 0x01, 0x69, 0x06, 0x01, 0x01, 0x01, 0x67, 0x06, 0x01, 0x01, 0x01, 0x68, 0x06, 0x01, 0x01, 0x01, 0x74, 0x06, 0x01, 0x01, 0x01, 0x21, 0x06, 0x01, 0x01, 0x01, 0x0A, 0x06, 0x01, 0x18, 0x23, 0x01, 0x01, 0x57, 0x06, 0x01, 0x01, 0x01, 0x72, 0x06, 0x01, 0x01, 0x01, 0x6F, 0x06, 0x01, 0x01, 0x01, 0x6E, 0x06, 0x01, 0x01, 0x01, 0x67, 0x06, 0x01, 0x01, 0x01, 0x21, 0x06, 0x01, 0x01, 0x01, 0x0A, 0x06, 0x01, 0x00] pc=0 res=["Addr Code\n"] addrfmt="{0:0>4} " while pc<len(opcode): i=pc pc+=ins_set[opcode[i]][0] res.append(addrfmt.format(i)) if opcode[i] not in ins_set.keys(): #If the opcode does not exist in the instruction set print("[-] UknOpcode 0x{0:X} in addr 0x{1:0>8X}.\n".format(opcode[i],i)) break elif opcode[i]==0x08 or opcode[i]==0x18: jmpdelta=opcode[i+1] if opcode[i+1]&0x80==0 else opcode[i+1]-256 res.append(ins_set[opcode[i]][2].format(pc+jmpdelta)+'\n') else: #Handling of general opcode args=[] for j in range(ins_set[opcode[i]][1]): args.append(opcode[i+1+j]) res.append(ins_set[opcode[i]][2].format(*args)+'\n') if opcode[i]==0: break with open('res.txt','w') as f: f.writelines(res)
res.txt obtained:
Addr Code 0000 mov r1,0x00 0003 mov [r1],0x0A 0006 inc r1 0008 mov [r1],0x01 0011 inc r1 0013 mov [r1],0x0F 0016 inc r1 0018 mov [r1],0x08 0021 inc r1 0023 mov [r1],0x13 0026 inc r1 0028 mov [r1],0x7D 0031 inc r1 0033 mov [r1],0x5A 0036 inc r1 0038 mov [r1],0x1D 0041 inc r1 0043 mov [r1],0x01 0046 inc r1 0048 mov [r1],0x17 0051 inc r1 0053 mov [r1],0x79 0056 inc r1 0058 mov [r1],0x56 0061 inc r1 0063 mov [r1],0x13 0066 inc r1 0068 mov [r1],0x7E 0071 inc r1 0073 mov [r1],0x0F 0076 inc r1 0078 mov [r1],0x1A 0081 inc r1 0083 mov [r1],0x63 0086 inc r1 0088 mov [r1],0x1F 0091 inc r1 0093 mov [r1],0x11 0096 inc r1 0098 mov [r1],0x06 0101 inc r1 0103 mov [r1],0x1E 0106 inc r1 0108 mov [r1],0x0B 0111 inc r1 0113 mov [r1],0x13 0116 inc r1 0118 mov [r1],0x48 0121 inc r1 0123 mov [r1],0x1A 0126 inc r1 0128 mov [r1],0x11 0131 inc r1 0133 mov [r1],0x69 0136 inc r1 0138 mov [r1],0x1F 0141 inc r1 0143 mov [r1],0x44 0146 inc r1 0148 mov [r1],0x19 0151 inc r1 0153 mov [r1],0x13 0156 inc r1 0158 mov [r1],0x0E 0161 inc r1 0163 mov r1,0x57 0166 putchar(r1) 0168 mov r1,0x68 0171 putchar(r1) 0173 mov r1,0x61 0176 putchar(r1) 0178 mov r1,0x74 0181 putchar(r1) 0183 mov r1,0x20 0186 putchar(r1) 0188 mov r1,0x69 0191 putchar(r1) 0193 mov r1,0x73 0196 putchar(r1) 0198 mov r1,0x20 0201 putchar(r1) 0203 mov r1,0x79 0206 putchar(r1) 0208 mov r1,0x6F 0211 putchar(r1) 0213 mov r1,0x75 0216 putchar(r1) 0218 mov r1,0x72 0221 putchar(r1) 0223 mov r1,0x20 0226 putchar(r1) 0228 mov r1,0x66 0231 putchar(r1) 0233 mov r1,0x6C 0236 putchar(r1) 0238 mov r1,0x61 0241 putchar(r1) 0243 mov r1,0x67 0246 putchar(r1) 0248 mov r1,0x3F 0251 putchar(r1) 0253 mov r1,0x0A 0256 putchar(r1) 0258 mov r1,0x00 0261 r2 = getchar() 0263 push r2 0265 inc r1 0267 cmp r1,0x20 0270 jnz 0261 0272 mov r1,0x00 0275 add [r1],0x40 0278 inc r1 0280 cmp r1,0x20 0283 jnz 0275 0285 mov r1,0x40 0288 pop r2 0290 sub r1,0x01 0293 mov [r1],r2 0296 cmp r1,0x20 0299 jnz 0288 0301 mov r1,0x20 0304 mov r2,r1 0307 sub r2,0x20 0310 xor [r1],r2 0313 inc r1 0315 cmp r1,0x40 0318 jnz 0304 0320 mov r1,0x20 0323 add [r1],0x20 0326 inc r1 0328 cmp r1,0x40 0331 jnz 0323 0333 mov r1,0x00 0336 mov r2,0x20 0339 xor [r1],0xCC 0342 cmp [r1],[r2] 0345 jnz 0393 0347 inc r1 0349 inc r2 0351 cmp r1,0x20 0354 jnz 0339 0356 mov r1,0x52 0359 putchar(r1) 0361 mov r1,0x69 0364 putchar(r1) 0366 mov r1,0x67 0369 putchar(r1) 0371 mov r1,0x68 0374 putchar(r1) 0376 mov r1,0x74 0379 putchar(r1) 0381 mov r1,0x21 0384 putchar(r1) 0386 mov r1,0x0A 0389 putchar(r1) 0391 jmp 0428 0393 mov r1,0x57 0396 putchar(r1) 0398 mov r1,0x72 0401 putchar(r1) 0403 mov r1,0x6F 0406 putchar(r1) 0408 mov r1,0x6E 0411 putchar(r1) 0413 mov r1,0x67 0416 putchar(r1) 0418 mov r1,0x21 0421 putchar(r1) 0423 mov r1,0x0A 0426 putchar(r1) 0428 exit
It's a very standard ~ accurate compilation. It comes out after a little logic:
dst = [10, 1, 15, 8, 19, 125, 90, 29, 1, 23, 121, 86, 19, 126, 15, 26, 99, 31, 17, 6, 30, 11, 19, 72, 26, 17, 105, 31, 68, 25, 19, 14] flag = [] for i in range(32): flag.append((((dst[i]+64)^0xCC)-32)^i) print(''.join(map(chr,flag)))
flag: flag{T0ver_1s_my_boyfri3nd_h4ha}
Done, off duty (escape)