0%

nisc-flat

flat

flat_bdc004aa1104e443b3b9c90a6b98d5e6.zip

初步阅读f5代码,发现程序是由大量switch语句构成的,其中每个case都套上了很奇怪的数字,不方便静态阅读,所以我采取了动态调试的方式

发现大量诸如以下的语句

00040109E loc_40109E:                             ; CODE XREF: main:loc_4013B3↓j
.text:000000000040109E mov eax, [rbp+var_154]
.text:00000000004010A4 mov ecx, eax
.text:00000000004010A6 sub ecx, 88070986h
.text:00000000004010AC mov [rbp+var_164], eax
.text:00000000004010B2 mov [rbp+var_168], ecx
.text:00000000004010B8 jz loc_401270
.text:00000000004010BE jmp $+5
.text:00000000004010C3 ; ---------------------------------------------------------------------------
.text:00000000004010C3
.text:00000000004010C3 loc_4010C3: ; CODE XREF: main+7E↑j
.text:00000000004010C3 mov eax, [rbp+var_164]
.text:00000000004010C9 sub eax, 916CBF8Ch
.text:00000000004010CE mov [rbp+var_16C], eax
.text:00000000004010D4 jz loc_401382
.text:00000000004010DA jmp $+5

动态调试后可知程序把大量的汇编代码通过这样的方式混淆了,然后再通过操作码来读取对应的功能。

000401270 loc_401270:                             ; CODE XREF: main+78↑j
.text:0000000000401270 lea rdi, [rbp+s]
.text:0000000000401274 mov rax, offset aJ ; "J"
.text:000000000040127E mov ecx, 90h
.text:0000000000401283 mov edx, ecx ; n
.text:0000000000401285 lea rsi, [rbp+dest]
.text:000000000040128C mov [rbp+var_198], rdi
.text:0000000000401293 mov rdi, rsi ; dest
.text:0000000000401296 mov rsi, rax ; src
.text:0000000000401299 call _memcpy
.text:000000000040129E mov rdi, [rbp+var_198] ; char *
.text:00000000004012A5 call _Z10fun_check1Pc ; fun_check1(char *)
.text:00000000004012AA mov ecx, 916CBF8Ch
.text:00000000004012AF mov r8d, 70B25450h
.text:00000000004012B5 test al, 1
.text:00000000004012B7 cmovnz ecx, r8d
.text:00000000004012BB mov [rbp+var_154], ecx
.text:00000000004012C1 jmp loc_4013B3
.text:00000000004012C6 ; ---------------------------------------------------------------------------
.text:00000000004012C6
.text:00000000004012C6 loc_4012C6: ; CODE XREF: main+190↑j
.text:00000000004012C6 lea rdi, [rbp+s] ; char *
.text:00000000004012CA call _Z10fun_check2Pc ; 检测格式
.text:00000000004012CF mov ecx, 916CBF8Ch
.text:00000000004012D4 mov edx, 48DC1E73h
.text:00000000004012D9 test al, 1
.text:00000000004012DB cmovnz ecx, edx
.text:00000000004012DE mov [rbp+var_154], ecx
.text:00000000004012E4 jmp loc_4013B3
.text:00000000004012E9 ; ---------------------------------------------------------------------------
.text:00000000004012E9
.text:00000000004012E9 loc_4012E9: ; CODE XREF: main+174↑j
.text:00000000004012E9 lea rdi, [rbp+s] ; char *
.text:00000000004012ED call _Z10fun_check3Pc ; 限制格式
.text:00000000004012F2 mov ecx, 916CBF8Ch
.text:00000000004012F7 mov edx, 9FDEA8ECh
.text:00000000004012FC test al, 1
.text:00000000004012FE cmovnz ecx, edx
.text:0000000000401301 mov [rbp+var_154], ecx
.text:0000000000401307 jmp loc_4013B3
.text:000000000040130C ; ---------------------------------------------------------------------------
.text:000000000040130C
.text:000000000040130C loc_40130C: ; CODE XREF: main+B0↑j
.text:000000000040130C lea rdi, [rbp+s] ; char *
.text:0000000000401310 call _Z10fun_check4Pc ; 检查格式
.text:0000000000401315 mov ecx, 916CBF8Ch
.text:000000000040131A mov edx, 0CDC4B0D0h
.text:000000000040131F test al, 1
.text:0000000000401321 cmovnz ecx, edx
.text:0000000000401324 mov [rbp+var_154], ecx
.text:000000000040132A jmp loc_4013B3
.text:000000000040132F ; ---------------------------------------------------------------------------
.text:000000000040132F
.text:000000000040132F loc_40132F: ; CODE XREF: main+104↑j
.text:000000000040132F lea rsi, [rbp+dest] ; int *
.text:0000000000401336 lea rdi, [rbp+var_B0] ; char *
.text:000000000040133D call _Z10fun_check5PcPi ; fun_check5(char *,int *)
.text:0000000000401342 mov ecx, 916CBF8Ch
.text:0000000000401347 mov edx, 0F465F43Bh
.text:000000000040134C test al, 1
.text:000000000040134E cmovnz ecx, edx
.text:0000000000401351 mov [rbp+var_154], ecx
.text:0000000000401357 jmp loc_4013B3

check1~5是整个程序的核心部分,其中check1 ~check4都是对flag格式的限制

我们只需要将call checkx 打上断点,在这个call执行完成之后,观察al的值即可判断格式是否符合要求,最终发现flag的格式是flag{},总长度共42.

最重要的是check5函数,其中

.text:0000000000400D90 loc_400D90:                             ; CODE XREF: fun_check5(char *,int *)+E9↑j
.text:0000000000400D90 mov eax, 0B92BF994h
.text:0000000000400D95 mov ecx, 0AC151DE7h
.text:0000000000400D9A mov rdx, [rbp+var_10]
.text:0000000000400D9E movsxd rsi, [rbp+var_E4]
.text:0000000000400DA5 movsx edi, byte ptr [rdx+rsi] ; 读取下一个字符
.text:0000000000400DA9 cmp edi, 30h
.text:0000000000400DAC cmovge eax, ecx
.text:0000000000400DAF mov [rbp+var_E8], eax
.text:0000000000400DB5 jmp loc_40102D
.text:0000000000400DBA ; ---------------------------------------------------------------------------
.text:0000000000400DBA
.text:0000000000400DBA loc_400DBA: ; CODE XREF: fun_check5(char *,int *)+79↑j
.text:0000000000400DBA mov eax, 0B92BF994h
.text:0000000000400DBF mov ecx, 0E37ECC40h
.text:0000000000400DC4 mov rdx, [rbp+var_10]
.text:0000000000400DC8 movsxd rsi, [rbp+var_E4]
.text:0000000000400DCF movsx edi, byte ptr [rdx+rsi]
.text:0000000000400DD3 cmp edi, 39h ; 判断是否为数字
.text:0000000000400DD6 cmovle eax, ecx
.text:0000000000400DD9 mov [rbp+var_E8], eax
.text:0000000000400DDF jmp loc_40102D
.text:0000000000400DE4 ; ---------------------------------------------------------------------------
.text:0000000000400DE4
.text:0000000000400DE4 loc_400DE4: ; CODE XREF: fun_check5(char *,int *)+159↑j
.text:0000000000400DE4 mov rax, [rbp+var_10]
.text:0000000000400DE8 movsxd rcx, [rbp+var_E4]
.text:0000000000400DEF movsx edx, byte ptr [rax+rcx]
.text:0000000000400DF3 sub edx, 1D854A80h
.text:0000000000400DF9 add edx, 11h
.text:0000000000400DFC add edx, 1D854A80h
.text:0000000000400E02 movsxd rax, [rbp+var_E4]
.text:0000000000400E09 mov [rbp+rax*4+var_E0], edx
.text:0000000000400E10 mov [rbp+var_E8], 72D256E3h
.text:0000000000400E1A jmp loc_40102D

如果输入是数字,就将数字转换为对应的大写字母

.text:0000000000400E1F loc_400E1F:                             ; CODE XREF: fun_check5(char *,int *)+B1↑j
.text:0000000000400E1F mov eax, 966647E9h
.text:0000000000400E24 mov ecx, 0BA6BE5FDh
.text:0000000000400E29 mov rdx, [rbp+var_10]
.text:0000000000400E2D movsxd rsi, [rbp+var_E4]
.text:0000000000400E34 movsx edi, byte ptr [rdx+rsi]
.text:0000000000400E38 cmp edi, 2Dh
.text:0000000000400E3B cmovz eax, ecx
.text:0000000000400E3E mov [rbp+var_E8], eax
.text:0000000000400E44 jmp loc_40102D

‘-‘符号不作处理

.text:0000000000400E75 loc_400E75:                             ; CODE XREF: fun_check5(char *,int *)+41↑j
.text:0000000000400E75 mov eax, 67B6BD28h
.text:0000000000400E7A mov ecx, 0B80842FBh
.text:0000000000400E7F mov rdx, [rbp+var_10]
.text:0000000000400E83 movsxd rsi, [rbp+var_E4]
.text:0000000000400E8A movsx edi, byte ptr [rdx+rsi]
.text:0000000000400E8E cmp edi, 61h
.text:0000000000400E91 cmovge eax, ecx
.text:0000000000400E94 mov [rbp+var_E8], eax
.text:0000000000400E9A jmp loc_40102D
.text:0000000000400E9F ; ---------------------------------------------------------------------------
.text:0000000000400E9F
.text:0000000000400E9F loc_400E9F: ; CODE XREF: fun_check5(char *,int *)+95↑j
.text:0000000000400E9F mov eax, 67B6BD28h
.text:0000000000400EA4 mov ecx, 7CFC4F40h
.text:0000000000400EA9 mov rdx, [rbp+var_10]
.text:0000000000400EAD movsxd rsi, [rbp+var_E4]
.text:0000000000400EB4 movsx edi, byte ptr [rdx+rsi]
.text:0000000000400EB8 cmp edi, 7Ah
.text:0000000000400EBB cmovle eax, ecx
.text:0000000000400EBE mov [rbp+var_E8], eax
.text:0000000000400EC4 jmp loc_40102D
.text:0000000000400EC9 ; ---------------------------------------------------------------------------
.text:0000000000400EC9
.text:0000000000400EC9 loc_400EC9: ; CODE XREF: fun_check5(char *,int *)+271↑j
.text:0000000000400EC9 mov rax, [rbp+var_10]
.text:0000000000400ECD movsxd rcx, [rbp+var_E4]
.text:0000000000400ED4 movsx edx, byte ptr [rax+rcx]
.text:0000000000400ED8 sub edx, 50577E63h
.text:0000000000400EDE sub edx, 30h
.text:0000000000400EE1 add edx, 50577E63h
.text:0000000000400EE7 movsxd rax, [rbp+var_E4]
.text:0000000000400EEE mov [rbp+rax*4+var_E0], edx
.text:0000000000400EF5 mov [rbp+var_E8], 67B6BD28h
.text:0000000000400EFF jmp loc_40102D

如果是字母就转换为数字

最后在转换完成的字符串上面下一个内存断点,就可找到这个字符串与目标加密字符串比较的过程

加密字符串:

flag{J2261C63-3I2I-EGE4-IBCC-IE41A5I5F4HB}

解密即可。

en c = "J2261C63-3I2I-EGE4-IBCC-IE41A5I5F4HB"
flag = "flag{"

for c in enc:
if c == '-':
fuck = 0
elif c >= 'A' and c <= 'J':
c = chr(ord(c) - 0x11)
else:
c = chr(ord(c) + 48)
flag = flag + c

flag += '}'
print(flag)