GACTF 2020逆向部分WP
本帖最后由 镇北看雪 于 2020-9-1 22:25 编辑# 前言
***
论坛和网上还有很多解析,每个人思路有所不同有兴趣的可以结合着看。
# Simulator
***
这题的提示是Study 《Introduction to Computer System》 carefully,the format of flag is GACTF{},意思让我们好好学习计算机系统概论,计算机系统概论是一门计算机专业课,我们还没有教这门课。我们下面下载题目后看到题目是一个OBJ文件,懵逼OBJ文件怎么逆向吗!
不管了用WinHex打开看一下,发现一些关键字符。我们可以看到字符串意思是
Welcome to the world of LC3
Please input you flag:
Sussess!
Your flag is xctf{{you input}}
Try again!
Welcome to the world of LC3,从来没有听说过LC3是什么东西。这时我想到了那句提示Study 《Introduction to Computer System》 carefully,那咱们就百度一下搜一搜《计算机系统概论》,还真发现了LC3。原来LC3是一款较为成熟的16位汇编程序运行调试软件,2003年时由美国得克萨斯州立大学的 Yale N. Patt 和伊利诺伊大学香槟分校的 Sanjay J. Patel 两位计算机科学教授开发完成。
我们需要下载LC-3模拟器,一般这个模拟器会包含一个供编写LC3汇编程序的软件LC3Edit.exe,一般用LC3Edit.exe编写LC3汇编程序会生成一个OBJ文件供用户调试,调试此OBJ文件的软件为Simulate.exe。
我们打开Simulate软件并导入OBJ文件,下面我们可以看到程序的LC3汇编代码。我在做的时候因为没接触过LC3汇编,上网搜结果资料及其少。不知道每一条指令的意思只好一步一步跟然后自己猜测并结合网上极其少的LC3汇编指令的注解将程序的主要逻辑搞明白了。
对其LC3代码的主要逻辑与算法逆向分析如下
```
Memory:
x30001110000001111010xE07A LEA R0, x307B
x30011111000000100010xF022 TRAP PUTS //向屏幕输出字符串:“Welcome to the world of LC3”
x30020010000001110111x2077 LD R0, x307A
x30031111000000100001xF021 TRAP OUT
x30041110000010010010xE092 LEA R0, x3097
x30051111000000100010xF022 TRAP PUTS //向屏幕输出字符串:"Please input you flag: "
x30060010011011011110x26DE LD R3, x30E5 //R3 = 0x18
x30071111000000100000xF020 TRAP GETC //获得屏幕的输入的一个字符
x30081111000000100001xF021 TRAP OUT //将此字符显示到屏幕上
x30090010001011011010x22DA LD R1, x30E4 //R1 = 0x4000
x300A0001001001000011x1243 ADD R1, R1, R3 //R1 = R1 + R3
x300B0111000001000000x7040 STR R0, R1, #0 // = R0
x300C0001011011111111x16FF ADD R3, R3, #-1 //R3 = R3 - 1
x300D0000100000000001x0801 BRN x300F //if(R3 == 0)跳转0x300F
x300E0000111111111000x0FF8 BRNZPx3007 //无条件跳转到0x3007
x300F1110100011101111xE8EF LEA R4, x30FF //以上指令主要功能就是获得0x19个字符并将其倒序保存在0x4000开始的连续的内存空间中
x30100101010010100000x54A0 AND R2, R2, #0
x30110001001010000100x1284 ADD R1, R2, R4
x30120110001001000000x6240 LDR R1, R1, #0
x30130101000000100000x5020 AND R0, R0, #0
x30140010000001100010x2062 LD R0, x3077
x30151001000000111111x903F NOT R0, R0
x30160001000000100001x1021 ADD R0, R0, #1
x30170001000001000000x1040 ADD R0, R1, R0
x30180000010000001010x040A BRZ x3023
x30190010000001011110x205E LD R0, x3078
x301A1001000000111111x903F NOT R0, R0
x301B0001000000100001x1021 ADD R0, R0, #1
x301C0001000001000000x1040 ADD R0, R1, R0
x301D0000010000010111x0417 BRZ x3035
x301E0010000001011010x205A LD R0, x3079
x301F1001000000111111x903F NOT R0, R0
x30200001000000100001x1021 ADD R0, R0, #1
x30210001000001000000x1040 ADD R0, R1, R0
x30220000010000100101x0425 BRZ x3048
x30230001001010100001x12A1 ADD R1, R2, #1
x30240001001100000001x1301 ADD R1, R4, R1
x30250110001001000000x6240 LDR R1, R1, #0
x30260001110001100000x1C60 ADD R6, R1, #0
x30270001001010100010x12A2 ADD R1, R2, #2
x30280001001100000001x1301 ADD R1, R4, R1
x30290110001001000000x6240 LDR R1, R1, #0
x302A0010000010111001x20B9 LD R0, x30E4
x302B0001000001100000x1060 ADD R0, R1, #0
x302C0110000000000000x6000 LDR R0, R0, #0
x302D0001111000100000x1E20 ADD R7, R0, #0
x302E0001101001100000x1A60 ADD R5, R1, #0
x302F0000111000101001x0E29 BRNZPx3059
x30300010001010110011x22B3 LD R1, x30E4
x30310001001101000001x1341 ADD R1, R5, R1
x30320111000001000000x7040 STR R0, R1, #0
x30330001010010100011x14A3 ADD R2, R2, #3
x30340000111111011100x0FDC BRNZPx3011
x30350001001010100001x12A1 ADD R1, R2, #1
x30360001001100000001x1301 ADD R1, R4, R1
x30370110001001000000x6240 LDR R1, R1, #0
x30380010000010101011x20AB LD R0, x30E4
x30390001000000000001x1001 ADD R0, R0, R1
x303A0110110000000000x6C00 LDR R6, R0, #0 //R6 = flag
x303B0001001010100010x12A2 ADD R1, R2, #2
x303C0001001100000001x1301 ADD R1, R4, R1
x303D0110001001000000x6240 LDR R1, R1, #0
x303E0010000010100101x20A5 LD R0, x30E4
x303F0001000000000001x1001 ADD R0, R0, R1
x30400001101001100000x1A60 ADD R5, R1, #0 //R5 = n
x30410110111000000000x6E00 LDR R7, R0, #0 //R7 = flag
x30420000111000011000x0E18 BRNZPx305B //jmp 0x305B
x30430010001010100000x22A0 LD R1, x30E4 //R1 = 0x4000
x30440001001001000101x1245 ADD R1, R1, R5 //R1 = R1 + R5
x30450111000001000000x7040 STR R0, R1, #0 // = R0
x30460001010010100011x14A3 ADD R2, R2, #3
x30470000111111001001x0FC9 BRNZPx3011 //jmp 0x3011
x30480001001010100001x12A1 ADD R1, R2, #1
x30490001001100000001x1301 ADD R1, R4, R1
x304A0110001001000000x6240 LDR R1, R1, #0
x304B0001110001100000x1C60 ADD R6, R1, #0 //R6 = n
x304C0001001010100010x12A2 ADD R1, R2, #2
x304D0001001100000001x1301 ADD R1, R4, R1
x304E0110001001000000x6240 LDR R1, R1, #0
x304F0010101010010101x2A95 LD R5, x30E5
x30501001001001111111x927F NOT R1, R1
x30510001001001100001x1261 ADD R1, R1, #1
x30520001101101000001x1B41 ADD R5, R5, R1 //R5 = 0x18 - n
x30530001111101100000x1F60 ADD R7, R5, #0 //R7 = R5
x30540000111000001100x0E0C BRNZPx3061 //jmp 0x3061
x30550001101101100000x1B60 ADD R5, R5, #0 //关键跳转
x30560000010000010101x0415 BRZ x306C //if(n == 0),则跳到0x306C,flag正确
x30570001010010100011x14A3 ADD R2, R2, #3
x30580000111110111000x0FB8 BRNZPx3011
x30590001000110000111x1187 ADD R0, R6, R7
x305A0000111111010101x0FD5 BRNZPx3030
x305B1001000110111111x91BF NOT R0, R6
x305C0101000000000111x5007 AND R0, R0, R7 //R0 = ~R6 & R7
x305D1001001111111111x93FF NOT R1, R7
x305E0101001110000001x5381 AND R1, R6, R1 //R1 = ^R7 & R6
x305F0001000001000000x1040 ADD R0, R1, R0 //R0 = R0 + R1
x30600000111111100010x0FE2 BRNZPx3043 //jmp 0x3043
x30610010000010000010x2082 LD R0, x30E4
x30620001000000000110x1006 ADD R0, R0, R6
x30630110000000000000x6000 LDR R0, R0, #0 //R0 = 0x4000
x30641110001010000001xE281 LEA R1, x30E6
x30650001001001000111x1247 ADD R1, R1, R7
x30660110001001000000x6240 LDR R1, R1, #0 //R1 = 0x30EF
x30671001001001111111x927F NOT R1, R1
x30680001001001100001x1261 ADD R1, R1, #1 //关键判断,跳转处
x30690001000000000001x1001 ADD R0, R0, R1 //if(R0 == R1)
x306A0000010111101010x05EA BRZ x3055 //jmp 0x3055
x306B0000111000000101x0E05 BRNZPx3071
x306C0010000000001101x200D LD R0, x307A //输出Success!
x306D1111000000100001xF021 TRAP OUT
x306E1110000001000000xE040 LEA R0, x30AF //输出Your flag is xctf{{you input}}
x306F1111000000100010xF022 TRAP PUTS
x30700000111000000101x0E05 BRNZPx3076
x30710010000000001000x2008 LD R0, x307A //输出Try again!
x30721111000000100001xF021 TRAP OUT
x30731110000001100101xE065 LEA R0, x30D9 //输出----- Halting the processor -----
x30741111000000100010xF022 TRAP PUTS
x30750000111000000000x0E00 BRNZPx3076
x30761111000000100101xF025 TRAP HALT
x30770000000000010001x0011 NOP
x30780000000000010011x0013 NOP
x30790000000000010100x0014 NOP
```
算法大致就是对25个字符的flag进行加密后与0x30EF内存处的数组进行比较,我们在winHex中可以找到此数组的数据
而且由算法逆向可知,我们输入的flag的第一个字符必须为‘l’即值等于0x6c,最后我们根据其算法编写程序得到flag为:lc3_1s_small_but_complete
```
#include <iostream>
#include <Windows.h>
using namespace std;
int main()
{
BYTE a;
BYTE b;
BYTE F[] ={0x6C,0x0f, 0x50, 0x6c, 0x6e, 0x42, 0x2c, 0x2c, 0x1e,
0x0c, 0x0d, 0x0,0x33, 0x3d, 0x17, 0x01, 0x2b,
0x3c, 0x0c, 0x02, 0x1d, 0x1c, 0x09, 0x11, 0x11};
BYTE R1;
BYTE R0;
BYTE R5 = 24;
BYTE R6 = 0;
BYTE R7 = 24;
for(int i = 0;i <= 24; i++)
{
R7 = 24 - i;
R1 = F;
R1 = ~R1;
R1 = R1 + 1;
b = R1;
}
BYTE yy2 = 1;
BYTE yy1 = 1;
BYTE rr = 1;
BYTE yy11;
while(1)
{
while(yy2 < 0xff)
{
yy1 = 1;
while(yy1 < 0xff)
{
rr = (((~yy1) & yy2) + ((~yy2) & yy1) +b);
if(rr == 0)
{
if((yy1 >=0x21 && yy1<= 0x7e) && (yy2 >=0x21 && yy2<= 0x7e))
{
rr = 2;
break;
}
}
yy1++;
}
if(rr == 2)
break;
yy2++;
}
a = yy2;
a = yy1;
for(int i = 23; i >= 1; i--)
{
yy11 = 1;
while(yy11 < 0xff)
{
rr = (((~yy11) & a) + ( ~a & yy11) +b);
if(rr == 0)
{
if((yy11 >=0x21 && yy11<= 0x7e) && (yy2 >=0x21 && yy2<= 0x7e))
break;
}
yy11++;
}
a = yy11;
}
if(a == 'l')
break;
yy2++;
rr = 0;
}
printf("flag:%.24s\n", a);
return 0 ;
}
```
下面是我在寻找LC3汇编时候搜的的一些资源,关于LC3汇编调试器的使用,以及其指令系统,有兴趣的可以看看。
https://my.oschina.net/Samyan/blog/1614174/print
https://wenku.baidu.com/view/c322be9ab14e852459fb573b.html
# WannaFlag
***
此软件我们用Exeinfope分析后得其为32位可执行文件,无壳。
然后我们直接拖入OD运行,软件的页面有点防勒索软件的意思,并且放着诡异的音乐。其提示为需要输入正确的KEY,从而获得flag。还可以支付给作者6666人民币获得,可笑身为吾爱破解的资深菜鸟怎么可能丢这个人。准备开干!
按照一般思路,其让输入key并判断key,那就肯定需要获取edit控件的key值。对一些获取edit控件值的API下断点,如GetWindowTextA/W,GetDlgItemTextA/W等等。
我们输入123456位key后按DECRYPT FLAG。程序断在了GetWindowTextA函数的入口处。
接着我们ALT+F9返回到用户空间中。我们往下看发现其调用MessagBoxA显示orz,意思就是我们成功了。其上方的一些跳转都是关键跳转。我们往上分析汇编代码的含义及其算法实现。
```
005D2847 .83C4 0C add esp,0xC
005D284A .8D8424 200200>lea eax,dword ptr ss:
005D2851 .6A 20 push 0x20 ; /Count = 20 (32.)
005D2853 .50 push eax ; |Buffer
005D2854 .56 push esi ; |hWnd
005D2855 .FF15 FCB15E00 call Xdword ptr ds: ; \GetWindowTextA
005D285B .8DB424 200200>lea esi,dword ptr ss:
005D2862 .8D4E 01 lea ecx,dword ptr ds:
005D2865 >8A06 mov al,byte ptr ds:
005D2867 .46 inc esi
005D2868 .84C0 test al,al
005D286A .^ 75 F9 jnz X005D2865
005D286C .2BF1 sub esi,ecx
005D286E .83FE 06 cmp esi,0x6
005D2871 .0F8C 6A010000 jl 005D29E1 ;esi = key长度
005D2877 .0FBE8424 2402>movsx eax,byte ptr ss:
005D287F .B9 07000000 mov ecx,0x7
005D2884 .99 cdq
005D2885 .F7F9 idiv ecx ;edi = a % 7
005D2887 .8BFA mov edi,edx
005D2889 .8D51 FA lea edx,dword ptr ds: ;edx = 1
005D288C .B9 02000000 mov ecx,0x2 ;ecx = 2
005D2891 .3BF9 cmp edi,ecx
005D2893 .7E 08 jle X005D289D
005D2895 >0FAFD1 imul edx,ecx ;edx * ecx
005D2898 .41 inc ecx ;ecx = 3
005D2899 .3BCF cmp ecx,edi
005D289B .^ 7C F8 jl X005D2895
005D289D >33C0 xor eax,eax
005D289F .83FE 40 cmp esi,0x40
005D28A2 .0F82 7F000000 jb 005D2927
005D28A8 .8BCE mov ecx,esi
005D28AA .81E1 3F000080 and ecx,0x8000003F
005D28B0 .79 05 jns X005D28B7
005D28B2 .49 dec ecx
005D28B3 .83C9 C0 or ecx,0xFFFFFFC0
005D28B6 .41 inc ecx
005D28B7 >8BFE mov edi,esi
005D28B9 .2BF9 sub edi,ecx
005D28BB .0FBECA movsx ecx,dl
005D28BE .66:0F6EC1 movd mm0,ecx
005D28C2 .66:0F60C0 punpcklbw mm0,mm0
005D28C6 .66:0F61C0 punpcklwd mm0,mm0
005D28CA .66:0F70C8 00pshufw mm1,mm0,0x0
005D28CF .90 nop
005D28D0 >0F108404 2002>movups xmm0,dqword ptr ss:[esp+eax+0x220>
005D28D8 .66:0FEFC1 pxor mm0,mm1
005D28DC .0F118404 7802>movups dqword ptr ss:,xmm>
005D28E4 .0F108404 3002>movups xmm0,dqword ptr ss:[esp+eax+0x230>
005D28EC .66:0FEFC1 pxor mm0,mm1
005D28F0 .0F118404 8802>movups dqword ptr ss:,xmm>
005D28F8 .0F108404 4002>movups xmm0,dqword ptr ss:[esp+eax+0x240>
005D2900 .66:0FEFC1 pxor mm0,mm1
005D2904 .0F118404 9802>movups dqword ptr ss:,xmm>
005D290C .0F108404 5002>movups xmm0,dqword ptr ss:[esp+eax+0x250>
005D2914 .66:0FEFC1 pxor mm0,mm1
005D2918 .0F118404 A802>movups dqword ptr ss:,xmm>
005D2920 .83C0 40 add eax,0x40
005D2923 .3BC7 cmp eax,edi
005D2925 .^ 7C A9 jl X005D28D0
005D2927 >3BC6 cmp eax,esi
005D2929 .7D 1A jge X005D2945
005D292B 0F db 0F
005D292C 1F db 1F
005D292D 44 db 44 ;CHAR 'D'
005D292E 00 db 00
005D292F 00 db 00
005D2930 >8A8C04 200200>mov cl,byte ptr ss: ;cl = key
005D2937 .32CA xor cl,dl ;cl = cl ^ dl
005D2939 .888C04 780200>mov byte ptr ss:,cl ;0x003ff9A0 = cl
005D2940 .40 inc eax ;n++
005D2941 .3BC6 cmp eax,esi
005D2943 .^ 7C EB jl X005D2930 ;------------
005D2945 >C68404 780200>mov byte ptr ss:,0x0
005D294D .33D2 xor edx,edx
005D294F .90 nop
005D2950 >8A82 E00A5F00 mov al,byte ptr ds: ;al = 0x00CE0AE1
005D2956 .8ACA mov cl,dl
005D2958 .328414 780200>xor al,byte ptr ss: ;al = al ^ 0x003ff9A0
005D295F .D2C0 rol al,cl ;rol al , n
005D2961 .888414 780200>mov byte ptr ss:,al ;0x003ff9A0 = AL
005D2968 .42 inc edx
005D2969 .3BD6 cmp edx,esi
005D296B .^ 7C E3 jl X005D2950 ;---------------------
005D296D .8D8C24 780200>lea ecx,dword ptr ss:
005D2974 .BA D8785F00 mov edx,0x5F78D8 ;全局数组0x5f78d8
005D2979 .BE 1B000000 mov esi,0x1B ;esi = 0x1B
005D297E .66:90 nop
005D2980 >8B01 mov eax,dword ptr ds: ;判断加密后的key与0x5F78D8内存处数组的数据是否相等
005D2982 .3B02 cmp eax,dword ptr ds:
005D2984 75 5B jnz X005D29E1
005D2986 .83C1 04 add ecx,0x4
005D2989 .83C2 04 add edx,0x4
005D298C .83EE 04 sub esi,0x4
005D298F .^ 73 EF jnb X005D2980
005D2991 .66:8B01 mov ax,word ptr ds:
005D2994 .66:3B02 cmp ax,word ptr ds:
005D2997 .75 48 jnz X005D29E1
005D2999 .8A41 02 mov al,byte ptr ds:
005D299C .3A42 02 cmp al,byte ptr ds:
005D299F .75 40 jnz X005D29E1
005D29A1 .6A 00 push 0x0 ; /Style = MB_OK|MB_APPLMODAL
005D29A3 .68 980C5F00 push 0x5F0C98 ; |Title = "orz"
005D29A8 .68 980C5F00 push 0x5F0C98 ; |Text = "orz"
005D29AD .53 push ebx ; |hOwner
005D29AE .FF15 00B25E00 call Xdword ptr ds: ; \MessageBoxA
```
我们在内存窗口中查看0x5f78d8地址处的数组的数据。
接着我们根据逆向算法写出程序求得真正的key为:wannaflag_is_just_a_paper_tiger
需要注意的是rol运算的逆向在c语言ror指令的实现注意字节的大小,解密程序如下。
```
#include <iostream>
#include <Windows.h>
using namespace std;
#include <stdio.h>
unsigned ror(unsigned val, int size);
int main()
{
BYTE a = {0};
BYTE b[ ] = { 0x4E, 0xAE, 0x61, 0xBA, 0xE4, 0x2B, 0x55, 0xAA, 0x59, 0xFC, 0x4D, 0x02, 0x17, 0x6B, 0x13, 0xA1,
0x41, 0xFE, 0x35, 0x0B, 0xB4, 0x0B, 0x52, 0x2F, 0x46, 0xCC, 0x35, 0x82, 0xE5, 0x88, 0x50};
BYTE c[ ] = "ANNAWGALFYBKVIAHMXTFCAACLAAAAYK";
BYTE d = {0};
for(int i = 0; i < 31; i++)
{
a = ror(b,i) ^ c;
}
BYTE flag = 0;
while(1)
{
for(int i = 0; i < 31; i++)
{
d = flag ^ a;
}
BYTE WW = 2;
BYTE WW2 = 1;
while((d % 7) > WW)
{
WW2 = WW2 * WW;
WW++;
}
if(flag == WW2)
break;
flag++;
}
printf("flag:%s\n", d);
}
unsigned ror(unsigned val, int size)
{
unsigned res = val >> (size) % 8;
res |= val << (8 - (size % 8)) ;
return res;
}
```
接着输入正确的key后用OD我们运行程序,发现程序利用key和flag.bin中的数据结合解密函数得到flag。并生成flag.txt文件,将flag写进去。
# Checkin
***
还是用Excinfope程序查壳,发现文件为32位程序无壳直接载入OD。
我们单步向下跟踪发现岂会利用内存映射文件,将自身文件的附件数据通过创建文件并写入。
接着单步往下跟踪我们发现其实际是在路径C:\Users\ADMINI~1\AppData\Local\Temp\ocrA147.tmp下创建大量文件。
我们继续向下单步跟踪发现岂会创建一个新的进程,C:\Users\ADMINI~1\AppData\Local\Temp\ocrA147.tmp\bin\ruby.exe。此程序也是刚刚程序自己生成的文件。其通过CteateProessA创建此程序后,调用WaitForSingleObject()函数等待进程返回(此函数为阻塞函数)。当进程返回后程序调用GetExitCodeProess()获得程序结束的代码作进一步处理。
我们在WaitForSingleObject调用的下一条指令下断点,运行程序输入flag回车后,显示no,且WaitForSingleObjet函数返回,程序中断在刚刚下的断点处。
我们查看程序为单线程,所以不可能是此程序的其他线程进行的flag的判断。所以肯定是CreateProessA创建的Ruby.exe进行的判断。
我们来到ruby程序的文件夹下发现实际此程序是ruby编程语言脚本的执行程序。
我们在C:\Users\Administrator\AppData\Local\Temp\ocrA147.tmp\src目录下找到待执行的rb文件,其代码如下主要是采用了aes和base64加密。
```
require 'openssl'
require 'base64'
def aes_encrypt(key,encrypted_string)
aes = OpenSSL::Cipher.new("AES-128-ECB")
aes.encrypt
aes.key = key
cipher = aes.update(encrypted_string) << aes.final
return Base64.encode64(cipher)
end
print "Enter flag: "
flag = gets.chomp
key = "Welcome_To_GACTF"
cipher = "4KeC/Oj1McI4TDIM2c9Y6ahahc6uhpPbpSgPWktXFLM=\n"
text = aes_encrypt(key,flag)
if cipher == text
puts "good!"
else
puts "no!"
End
```
我们由加密程序写出解密程序,代码如下
```
require 'openssl'
require 'base64'
def aes_dicrypt(key,dicrypted_string)
cipher = Base64.decode64(dicrypted_string)
aes = OpenSSL::Cipher.new("AES-128-ECB")
aes.decrypt
aes.key = key
cipher = aes.update(cipher) << aes.final
return cipher
end
key = "Welcome_To_GACTF"
cipher = "4KeC/Oj1McI4TDIM2c9Y6ahahc6uhpPbpSgPWktXFLM=\n"
flag = aes_dicrypt(key,cipher)
printf("flag:%s\n",flag)
```
在cmd命令行运行程序得到flag。
我同时好奇其是如何从一个程序(ruby.exe)在另一个程序的cmd获得控制台输入的,经过对ruby的逆向分析发现。其实通过建立与Checkin.exe程序之间的管道,ruby.exe通过管道借助ReadFile()函数来获得Checkin.exe的控制台的输入的。
镇北看雪 发表于 2020-8-31 09:44
不是吧,这比赛不就前10名才有机会。后面的都是陪跑我觉得没什么关系才发的,要不然我是不会发的
不管什么时候规则也需要遵守,这是最基本的底线,你可以比赛结束后24小时发表wp,但是比赛时就发布wp,我可以认为你是在向比赛规则挑衅。 镇北看雪 发表于 2020-8-31 09:44
不是吧,这比赛不就前10名才有机会。后面的都是陪跑我觉得没什么关系才发的,要不然我是不会发的
@gink 说的很有道理,比赛没结束,确实禁止公开讨论,现在结束了吗?如果没结束把帖子权限编辑一下,不要公开。 支持支持 太猛 厉害,高手 。 GACTF比赛还未结束,你就投稿wp,一般个人wp在比赛结束后24小时才能发出,你这样严重违反比赛规则,建议撤销帖子 gink 发表于 2020-8-31 09:42
GACTF比赛还未结束,你就投稿wp,一般个人wp在比赛结束后24小时才能发出,你这样严重违反比赛规则,建议撤 ...
不是吧,这比赛不就前10名才有机会。后面的都是陪跑我觉得没什么关系才发的,要不然我是不会发的 坐等大佬 抓紧学习一下 不错的分析,支持分享
页:
[1]
2