日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

攻防世界RE练习区题目总结(1-10)

發(fā)布時(shí)間:2024/3/13 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 攻防世界RE练习区题目总结(1-10) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

前言
這篇文章是我做完攻防世界練習(xí)區(qū)的題目后對(duì)這十道題做的總結(jié)。emmm,其實(shí)這幾道題我?guī)讉€(gè)月前就做完了,這幾天又回去試著再做一遍發(fā)現(xiàn)還是有一些地方存在疑惑,并且速度也沒有太大的提升。所以決定把之前做過的題目整理一下都寫在博客里,便于以后復(fù)習(xí)順便把一些我沒搞懂的地方也記錄在這里,希望以后可以解決。也希望能有大佬有緣看到我這個(gè)小菜鳥的文章,可以幫我指點(diǎn)迷津。
這一篇只寫攻防世界新手區(qū)的幾道題,之后我還會(huì)把BUUCTF做的題也做個(gè)總結(jié),寫一篇博客,希望可以把這個(gè)習(xí)慣保持下去。說了這么多廢話,下面開始正文。

第一題:open-source


首先把附件下載下來,在exeinfope里查殼(雖然第一道題基本上沒有加殼的可能性,但我覺得這是個(gè)很好的習(xí)慣) 可見這個(gè)文件沒有加殼。這個(gè)文件的后綴是.c,所以直接在IDE里打開,這里我用的是DEVC++
#include <stdio.h>
#include <string.h>

int main(int argc, char *argv[]) {
if (argc != 4) {
printf(“what?\n”);
exit(1);
}

unsigned int first = atoi(argv[1]); if (first != 0xcafe) {printf("you are wrong, sorry.\n");exit(2); }unsigned int second = atoi(argv[2]); if (second % 5 == 3 || second % 17 != 8) {printf("ha, you won't get it!\n");exit(3); }if (strcmp("h4cky0u", argv[3])) {printf("so close, dude!\n");exit(4); }printf("Brr wrrr grr\n");unsigned int hash = first * 31337 + (second % 17) * 11 + strlen(argv[3]) - 1615810207;printf("Get your key: "); printf("%x\n", hash); return 0;

}`
由最后的兩個(gè)printf語句可以看出flag就是hash,由%x可以看出是十六進(jìn)制表示。
所以向上看對(duì)hash進(jìn)行運(yùn)算的只有

unsigned int hash = first * 31337 + (second % 17) * 11 + strlen(argv[3]) - 1615810207;

可知hash的值與first,second,argv[3]的值有關(guān),從上面的3個(gè)if語句可以判斷出:當(dāng)if()里的條件為真時(shí),都會(huì)提示錯(cuò)誤并退出程序,所以3個(gè)if()里的條件都為假,所以可以推測(cè)出下列條件;first=0xcafe,second % 5 != 3&&second % 17 == 8(最小的second是25),argv[3]=h4cky0u(所以strlen(argv[3])=7)。將上述條件帶入計(jì)算hash的那段代碼可以得出hash,下面是我寫的代碼`#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
int first=0xcafe;
int second=25;
int a=7;

int hash=0; hash=first * 31337 + (second % 17) * 11 + 7 - 1615810207;printf("%x",hash); return 0;

}`
結(jié)果是
所以flag就是c0ffee。
第一題拿下!

第二題:simple-unpack


由題目描述可以看出這是一個(gè)加殼的文件,所以先拖到exeinfope里查殼


可以看出加了UPX這一類殼。所謂加殼就是為了隱藏程序真正的OEP(入口點(diǎn)),所以為了正常地打開程序使程序正常運(yùn)行,我們必須脫殼。我選擇的是用upx脫殼。

脫殼成功!關(guān)于upx脫殼我之前看到一篇博客講得挺詳細(xì)的,我把超鏈接放在下面。
使用upx脫殼工具脫殼
脫殼結(jié)束后再把脫殼后的文件放在exeinfope里看一下。

可以看到現(xiàn)在已經(jīng)沒有UPX殼了,之后把文件拉到IDA里打開。


按F5反匯編后發(fā)現(xiàn)flag相當(dāng)可疑,雙擊flag追蹤過去看到

發(fā)現(xiàn)了flag{Upx_1s_n0t_a_d3liv3r_c0mp4ny}。
第二題拿下!

第三題:logmein


下載附件后老規(guī)矩拿到exeinfope里查殼,


發(fā)現(xiàn)沒殼,而且是64位的文件,所以放到IDA64里靜態(tài)分析。ctrl+f搜索main函數(shù),再按F5反匯編,如圖


雙擊sub_4007F0看到


說明輸入正確的flag會(huì)讓程序輸出上述printf的一句話并退出。
再雙擊sub_4007C0看到


所以當(dāng)輸入錯(cuò)誤的flag時(shí)會(huì)使程序輸出上述一句話并退出。
所以不能讓程序運(yùn)行sub_4007C0這個(gè)函數(shù),所以*s[i] = (char)(*((_BYTE )&v7 + i % v6) ^ v8[i])
必須成立。去上面的代碼找到v7,v6,v8[]


看出v6=7 , v8[]=:"AL_RT^L*.?+6/46 , v7=28537194573619560LL,將28537194573619560LL轉(zhuǎn)換成字符,如圖
因?yàn)镮DA是小段法存儲(chǔ),所以真正的v7應(yīng)該是ebmarah倒過來變成harambe。下面是我寫的解題代碼

#include <stdio.h> #include <stdlib.h> #include <string.h>int main() {char v8[50]=":\"AL_RT^L*.?+6/46";char v7[50]="harambe";int v6 =7;char flag[50];for ( int i = 0; i < strlen(v8); ++i ){flag[i] = (char)(*((unsigned char*)&v7 + i % v6) ^ v8[i]) ;}printf("%s",flag);return 0; }

結(jié)果為


第三題拿下!

第四題:insanity


老規(guī)矩先把附件下載后放在exeinfope里查殼


看出文件無殼且是32位的,用IDA打開


發(fā)現(xiàn)整段代碼沒有什么運(yùn)算,感覺&strs有點(diǎn)可疑,雙擊進(jìn)去


發(fā)現(xiàn)9447{This_is_a_flag}…感覺簡(jiǎn)單得有點(diǎn)過分

又去字符串窗口看了一下

flag確實(shí)就是這個(gè)了(難道這才是第一題?)

第五題:python-trade


老規(guī)矩查殼


無殼是用python寫的。發(fā)現(xiàn)IDA打開之后無法反匯編,所以當(dāng)時(shí)我去找了一些博客,發(fā)現(xiàn)是要用python反匯編,這里我用的是在線Python反匯編,超鏈接我放在下面。

在線Python反編譯工具

推測(cè)出當(dāng)flag在encode函數(shù)中加密后與correct相等就成功。


由這一段看出將correct通過base64解碼后,經(jīng)過xor異或可以再得出原來的flag。
下面是我寫的解題代碼

import base64correct = 'XlNkVmtUI1MgXWBZXCFeKY+AaXNt' the_flag = base64.b64decode(correct)flag='' for i in the_flag:x =(ord(chr(i))-16) ^ 32flag+=chr(x)print(flag)

得出結(jié)果nctf{d3c0mpil1n9_PyC}

第五題拿下!

第六題:re1


老規(guī)矩先查殼


無殼且是32位,拉到IDA里反匯編


雙擊aFlag_0進(jìn)去


發(fā)現(xiàn)aFlag_0意思是flag錯(cuò)誤,雙擊unk_413E90進(jìn)去


發(fā)現(xiàn)顯示的是flag get,所以正確的flag會(huì)使程序進(jìn)行unk_413E90

所以if()里的條件要為假才可以不進(jìn)行aFlag_0,所以v3要為0
因?yàn)関3是由 *v3 = strcmp((const char )&v5, &v9) 決定的,當(dāng)v5=v9時(shí)v3才=0,發(fā)現(xiàn)v9由 **_mm_storeu_si128((__m128i )&v5, _mm_loadu_si128((const __m128i )&xmmword_413E34))決定,
發(fā)現(xiàn)
xmmword_413E34
有點(diǎn)可疑,雙擊進(jìn)去

猜測(cè)v9就等于xmmword的值,將3074656D30633165577B465443545544h轉(zhuǎn)換成字符


因?yàn)镮DA是小端法,所以這一串字符應(yīng)該反過來輸出,即為DUTCTF{We1c0met0}
一看就知道這就是flag

第六題拿下!

第七題:game


老規(guī)矩下載之后放到exeinfope里查殼


發(fā)現(xiàn)無殼且是32位的exe文件,發(fā)現(xiàn)是exe可執(zhí)行文件,直接雙擊打開


這一看我就樂了,經(jīng)典點(diǎn)燈小游戲,簡(jiǎn)單地說就是12345678分別控制1234578這8盞燈及其相鄰的燈的滅亮(1和8也算作相鄰的),了解過這個(gè)游戲的都知道直接按12345678的順序點(diǎn)一遍就可以全部點(diǎn)亮了。全點(diǎn)亮后如下圖


……發(fā)現(xiàn)flag真的出來了。

下面放在IDA里看一下,發(fā)現(xiàn)下面這一段很明顯是判斷燈是否全亮的


雙擊sub_457AB4()進(jìn)去,最后發(fā)現(xiàn)一段循環(huán)異或,猜測(cè)這就是flag的算法


寫一段代碼把v2到v58,v59到v115的值分別放在2個(gè)數(shù)組里,再進(jìn)行異或運(yùn)算,最后輸出結(jié)果。

#include<stdio.h> #include<string.h> #include<stdlib.h>int main() {int a[57]={123,32,18,98,119,108,65,41,124,80,125,38,124,111,74,49,83,108,94,108,84,6,96,83,44,121,104,110,32,95,117,101,99,123,127,119,96,48,107,71,92,29,81,107,90,85,64,12,43,76,86,13,114,1,117,126,0};int b[57]={18,64,98,5,2,4,6,3,6,48,49,65,32,12,48,65,31,78,62,32,49,32,1,57,96,3,21,9,4,62,3,5,4,1,2,3,44,65,78,32,16,97,54,16,44,52,32,64,89,45,32,65,15,34,18,16,0};for (int i = 0; i < 57; ++i ){a[i] ^= b[i];a[i] ^= 0x13u;printf("%c",a[i]);}return 0; }

(把這些數(shù)據(jù)拿到數(shù)組里真是太麻煩了,本人太菜,一個(gè)個(gè)復(fù)制粘貼過去的,有大佬知道什么快速的方法希望能告訴我 (~ ̄▽ ̄)~)

有個(gè)地方我想說一下,本來我的代碼是把printf放到for循環(huán)之外的,我打算一次性輸出整個(gè)字符串,但是控制臺(tái)老是顯示NULL,我到現(xiàn)在也不清楚是為什么,最后只能一個(gè)一個(gè)字符輸出了,有大佬知道為什么的話希望能告知 o()o。

最后結(jié)果如下圖


第七題拿下!

第八題:Hello,CTF


老規(guī)矩下載附件拖到exeinfope查殼


發(fā)現(xiàn)無殼且是32位的exe文件,嘖嘖,一看又是exe我想不會(huì)又可以不寫代碼直接玩出flag吧,結(jié)果我雙擊進(jìn)去發(fā)現(xiàn)只有一句話:please input your serial:……emmm還是老老實(shí)實(shí)的IDA打開吧。ctrl+F查找main之后按F5反匯編,然后直接去找判斷成功的代碼如下


看出v3要大于等于17,并且v10與v13要相同才可以進(jìn)行aSuccess。繼續(xù)往上看

要輸入v9,并且v9的長度要小于等于17,然后在do循環(huán)里把v9[v3]賦給v4,發(fā)現(xiàn)sprintf很像printf,猜測(cè)是輸出函數(shù),感覺asc_408044可疑,雙擊進(jìn)去發(fā)現(xiàn)


有%x表示十六進(jìn)制,猜測(cè)sprintf就是把v4用十六進(jìn)制表示,再往上看


發(fā)現(xiàn)v13=437261636b4d654a757374466f7246756e,所以flag應(yīng)該就是把437261636b4d654a757374466f7246756e用十六進(jìn)制表示出來,為了方便我就直接用在線轉(zhuǎn)換工具把它轉(zhuǎn)換成16進(jìn)制了,結(jié)果如下。


flag就是CrackMeJustForFun
第八題拿下!

第九題:no-strings-attached


老規(guī)矩下載附件拉到exeinfope查殼。


發(fā)現(xiàn)無殼且是32位的,拉到IDA里去反匯編,發(fā)現(xiàn)main函數(shù)反匯編后只有這些東西


發(fā)現(xiàn)authenticate是證實(shí)的意思,所以猜測(cè)flag與authenticate有關(guān)系,雙擊進(jìn)去看見


發(fā)現(xiàn)最后的if-else與判斷勝負(fù)的函數(shù)很像,雙擊unk_8048B44進(jìn)去


發(fā)現(xiàn)有Success,估計(jì)正確的flag就可以進(jìn)入unk_8048B44
發(fā)現(xiàn)wcscmp和strcmp很像估計(jì)作用也是一樣的,就是當(dāng)ws=s2的時(shí)候就可以進(jìn)入if了,再往上看發(fā)現(xiàn)decrypt函數(shù),decrypt是翻譯的意思,猜測(cè)是加密函數(shù),雙擊進(jìn)去。


發(fā)現(xiàn)這段代碼先把s的值復(fù)制給dest,然后將dest的每個(gè)值減去a2的每個(gè)值,然后返回值是dest,從原函數(shù)可知dest的值就是之前的s2。接下來就是要找出傳入的s和a2的值,即原來的s和dword_8048A90,雙擊原來的dword_8048A90進(jìn)去,看見了s和dword_8048A90的值,分別選中它們的值后按Shift+E,選擇C無符號(hào)字符數(shù)組(十進(jìn)制),將值復(fù)制下來準(zhǔn)備寫解題代碼時(shí)用。記得最后的4個(gè)0不要復(fù)制,因?yàn)樽址J(rèn)結(jié)尾為0。



下面是我寫的解題代碼。

#include<stdio.h> #include<string.h> #include<stdlib.h>int main() {int a2[]={1,20,0,0,2,20,0,0,3,20,0,0,4,20,0,0,5,20,0,0};int s[]={58,20,0,0,54,20,0,0,55,20,0,0,59,20,0,0,128,20,0,0,122,20,0,0,113,20,0,0,120,20,0,0,99,20,0,0,102,20,0,0,115,20,0,0,103,20,0,0,98,20,0,0,101,20,0,0,115,20,0,0,96,20,0,0,107,20,0,0,113,20,0,0,120,20,0,0,106,20,0,0,115,20,0,0,112,20,0,0,100,20,0,0,120,20,0,0,110,20,0,0,112,20,0,0,112,20,0,0,100,20,0,0,112,20,0,0,100,20,0,0,110,20,0,0,123,20,0,0,118,20,0,0,120,20,0,0,106,20,0,0,115,20,0,0,123,20,0,0,128,20,0,0,0,0,0,0,83,0,0,0,117,0,0,0,99,0,0,0,99,0,0,0,101,0,0,0,115,0,0,0,115,0,0,0,33,0,0,0,32,0,0,0,87,0,0,0,101,0,0,0,108,0,0,0,99,0,0,0,111,0,0,0,109,0,0,0,101,0,0,0,32,0,0,0,98,0,0,0,97,0,0,0,99,0,0,0,107,0,0,0,33,0,0,0,10,0,0,0};int x=0,i=0,j=0;while ( i < 156 ){x=s[i++]-a2[j++%20];//寫EXP的要點(diǎn)是把字符都轉(zhuǎn)換成整數(shù),并且最后一個(gè)一個(gè)地將整數(shù)換成字符輸出 ,之前也提過了,為了加深我自己的印象,又啰嗦了一遍 // if(x>32){printf("%c",x); // }} // 這里我把if(x>32)給注釋掉了,如果直接用這段代碼,會(huì)發(fā)現(xiàn)結(jié)果的字符之間會(huì)有很多的空格,為了消除這些空格,我設(shè)置了x>32這個(gè)條件,因?yàn)榭崭竦腁SCII代碼對(duì)應(yīng)的十進(jìn)制是32return 0; }

最后刪去空格的結(jié)果如下


第九題拿下!

第十題:maze


l老規(guī)矩拿到附件之后查殼


發(fā)現(xiàn)無殼且是64位的文件,根據(jù)題目描述這應(yīng)該是一道迷宮題。關(guān)于迷宮題,我當(dāng)時(shí)做完這道題之后專門去找了一些資料學(xué)習(xí),其中有一篇博客講的很好,由題目也有解析,我把超鏈接和網(wǎng)址放在下面。
逆向迷宮題總結(jié)
網(wǎng)址:https://blog.csdn.net/weixin_50549897/article/details/110633105

用IDA打開文件,ctrl+F查找main函數(shù),F5反匯編之后,看了看發(fā)現(xiàn)有4個(gè)if語句,因?yàn)槭敲詫m題,所以推測(cè)這四個(gè)if就是用來判斷上下左右的,把if()里的數(shù)字都換成字符,發(fā)現(xiàn)4個(gè)方向鍵是 ‘O’ , ‘o’ , ‘.’ , ‘0’ 。發(fā)現(xiàn)四個(gè)if語句最后都會(huì)到LABEL_14,一直追蹤下去,發(fā)現(xiàn)如下代碼

發(fā)現(xiàn)**if ( asc_601060[8 * (signed int)v10 + SHIDWORD(v10)] != ‘#’ )**應(yīng)該就是判斷是否到達(dá)終點(diǎn)的函數(shù),雙擊asc_601060進(jìn)去發(fā)現(xiàn)如下圖
數(shù)了數(shù)空格,*,#一共有64個(gè)字符,推測(cè)應(yīng)該是8x8的迷宮
四個(gè)if語句進(jìn)行的函數(shù)代碼如下

bool __fastcall sub_400650(_DWORD *a1)//對(duì)應(yīng)O {int v1; // eaxv1 = (*a1)--;return v1 > 0; } bool __fastcall sub_400660(int *a1)//對(duì)應(yīng)o {int v1; // eaxv1 = *a1 + 1;*a1 = v1;return v1 < 8; } bool __fastcall sub_400670(_DWORD *a1)//對(duì)應(yīng). {int v1; // eaxv1 = (*a1)--;return v1 > 0; } bool __fastcall sub_400680(int *a1)//對(duì)應(yīng)0 {int v1; // eaxv1 = *a1 + 1;*a1 = v1;return v1 < 8; }

可以看出上下和左右應(yīng)該分別由 ‘O’,‘o’ 和 ‘.’ ,'0’控制,并且發(fā)現(xiàn)有>0和<8來控制邊界所以可以確定這個(gè)迷宮就是8x8的迷宮了。
因?yàn)镺和o傳入的參數(shù)是+1的,4個(gè)方向函數(shù)傳入的參數(shù)都是4個(gè)字節(jié)的,所以O(shè)和o應(yīng)該是高位4字節(jié),而.和0應(yīng)該是低位4字節(jié),推測(cè)高位決定行低位決定列,所以推測(cè)O和o應(yīng)該決定左右,.和0應(yīng)該決定上下,所以上下左右分別為 ‘.’ , ‘0’ , ‘O’,‘o’ .方向搞定。。再往上看發(fā)現(xiàn)如下代碼

puts("Input flag:");scanf("%s", &s1, 0LL);if ( strlen(&s1) != 24 || strncmp(&s1, "nctf{", 5uLL) || *(&byte_6010BF + 24) != '}' )

可以看出輸入的s1就是flag,并且flag的長度等于24,并且開頭前5個(gè)字符就是 “nctf{”,并且結(jié)尾的字符是 ‘}’。所以能夠操作的步數(shù)是并且只能是24-6=18步,下面是我寫的打印迷宮的代碼。

#include <stdio.h> #include <stdlib.h> #include <string.h>int main() {char v[100]=" ******* * **** * **** * *** *# *** *** *** *********";printf("%d\n",strlen(v));for(int i=0;i<64;i++){printf("%c",v[i]);if((i+1)%8==0){printf("\n");}}return 0; }

打印出來為


其中*為墻壁,空格為可走的路徑。走幾次迷宮就可以判斷出來走法了,走法為:右下右右下下左下下下右右右右上上左左,所以flag=nctf{o0oo00O000oooo…OO}。
第十題拿下!

總結(jié)


首先當(dāng)時(shí)做題時(shí)遇到的最大問題就是見過的題目太少,基本每一道題都是新的題型,媒體都要去查資料。所以我認(rèn)為,想要提高自己的技術(shù),最重要的就是要都做題,關(guān)鍵是做不同類型的題,不然很容易遇到無從下手的情況。
還有兩道題我還要再琢磨一下,這次再次回顧做題的時(shí)候發(fā)現(xiàn)那兩道題思路還是不太清晰,所以我這次沒有寫進(jìn)來。等之后有空我就會(huì)寫出來的。

后續(xù)要學(xué)習(xí)的東西,在此立個(gè)flag

1.脫殼方法與技術(shù)
目前脫殼我只會(huì)用upx脫殼,但我之前在找資料的時(shí)候看到很多大佬都是用的ollydbg動(dòng)態(tài)調(diào)試來脫殼的,之后我肯定是要重點(diǎn)學(xué)習(xí)一下的。
2.相關(guān)匯編基礎(chǔ)打牢
沒有系統(tǒng)地專門學(xué)習(xí)過匯編,只是在網(wǎng)上找資料學(xué)會(huì)了一些皮毛,對(duì)于堆棧的理解還是不夠深刻,之后也要找時(shí)間打打牢。
3.做題做題再做題
果然做題才是積累經(jīng)驗(yàn)的好方法,之后題目肯定不能斷
4.博客繼續(xù)寫
這次回顧攻防世界的題目讓我再次對(duì)自己的記性產(chǎn)生了懷疑,果然好記性不如爛筆頭,之后每做完一些題我都要寫一下博客。

總結(jié)

以上是生活随笔為你收集整理的攻防世界RE练习区题目总结(1-10)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。