XCTF easyCpp buu [MRCTF2020]EasyCpp
文章目錄
- easyCpp
- transform分析
- accumulate分析
- 代碼實現
- [MRCTF2020]EasyCpp
- main::{lambda(int &)#1}
- lambda(int &)#1
- :operator++(_QWORD *a1)
easyCpp
簡單題目,只是傷眼而已。
大概分析了一下,有實際作用的也就兩個函數。
transform和accumulate,接下來,逐漸展開。拖進ida
for ( i = 0; i <= 15; ++i ){scanf("%d", &v26[4 * (signed __int64)i], v16);std::vector<int,std::allocator<int>>::push_back((__int64)&v20, (__int64)&v26[4 * i]);}輸入東西進行相應的初始化。。
for ( j = 0; j <= 15; ++j ){LODWORD(v25) = fib(j);std::vector<int,std::allocator<int>>::push_back(&v19, &v25);}fib(j)進去看了一下也就是生成相應長度的斐波那契數列
push_back函數作用大概用猜都能猜完,只不過每個push_back都不一樣,最好還是進去看看。
transform分析
__int64 __fastcall std::transform<__gnu_cxx::__normal_iterator<int *,std::vector<int,std::allocator<int>>>,std::back_insert_iterator<std::vector<int,std::allocator<int>>>,main::{lambda(int)#1}>(__int64 a1, __int64 a2, __int64 a3, __int64 a4) {int *v4; // rax@3__int64 *v5; // rax@3__int64 result; // rax@4__int64 v7; // rcx@4__int64 v8; // [sp+0h] [bp-30h]@1__int64 v9; // [sp+8h] [bp-28h]@1__int64 v10; // [sp+10h] [bp-20h]@1__int64 v11; // [sp+18h] [bp-18h]@1int v12; // [sp+24h] [bp-Ch]@3__int64 v13; // [sp+28h] [bp-8h]@1v11 = a1; v10 = a2; v9 = a3; v8 = a4; v13 = *MK_FP(__FS__, 40LL);while ( __gnu_cxx::operator!=<int *,std::vector<int,std::allocator<int>>>((__int64)&v11, (__int64)&v10) ){v4 = (int *)__gnu_cxx::__normal_iterator<int *,std::vector<int,std::allocator<int>>>::operator*((__int64)&v11);v12 = main::{lambda(int)#1}::operator() const((_DWORD **)&v8, *v4);v5 = (__int64 *)std::back_insert_iterator<std::vector<int,std::allocator<int>>>::operator*((__int64)&v9);std::back_insert_iterator<std::vector<int,std::allocator<int>>>::operator=(v5, (__int64)&v12);__gnu_cxx::__normal_iterator<int *,std::vector<int,std::allocator<int>>>::operator++(&v11);// v11++std::back_insert_iterator<std::vector<int,std::allocator<int>>>::operator++((__int64)&v9);// v9++}result = v9;v7 = *MK_FP(__FS__, 40LL) ^ v13;return result; }接下來進行簡略分析:
v11 = a1;根據函數外面分析這個也就是第二個元素的地址
v10 = a2;根據函數外面分析這個也就是最后一個元素的地址
v9 = a3; v8 = a4;而這兩個所指的地方的話,它都是一樣的,都是起始地址,輸入數據的起始地址。(在這里是不是有所疑問,為什么兩個指針指向同一個地方呢?)
然后是while循環分析:
v4 = (int *)__gnu_cxx::__normal_iterator<int *,std::vector<int,std::allocator<int>>>::operator*((__int64)&v11);遍歷取出從v11~v10的每一個元素
從這里分析,兩個指向相同地方的指針,v9在變化,它從v8始終不變,指向第一個元素。
得出,把v8加上(v11~v10)的每個元素,然后重新賦值給v9
很清楚了,這函數就是把我們輸入的值從第二個開始都加上第一個的值
至于這個v5是啥用,感覺是個中間變量。。。
accumulate分析
__int64 __usercall std::accumulate<__gnu_cxx::__normal_iterator<int *,std::vector<int,std::allocator<int>>>,std::vector<int,std::allocator<int>>,main::{lambda(std::vector<int,std::allocator<int>>,int)#2}>@<rax>(__int64 a1@<rdx>, __int64 a2@<rcx>, __int64 a3@<rdi>, __int64 a4@<rsi>, char a5) {int v5; // ebx@3__int64 result; // rax@4__int64 v7; // rcx@4__int64 v8; // [sp+0h] [bp-70h]@1__int64 v9; // [sp+8h] [bp-68h]@1__int64 v10; // [sp+10h] [bp-60h]@1__int64 v11; // [sp+18h] [bp-58h]@1char v12; // [sp+20h] [bp-50h]@3char v13; // [sp+40h] [bp-30h]@3__int64 v14; // [sp+58h] [bp-18h]@1v11 = a3; // 第二個元素地址v10 = a4; // 頭指針v9 = a1; // 尾指針v8 = a2;v14 = *MK_FP(__FS__, 40LL);while ( __gnu_cxx::operator!=<int *,std::vector<int,std::allocator<int>>>((__int64)&v10, (__int64)&v9) ){v5 = *(_DWORD *)__gnu_cxx::__normal_iterator<int *,std::vector<int,std::allocator<int>>>::operator*((__int64)&v10);// v5=&v10std::vector<int,std::allocator<int>>::vector((__int64)&v12, v8);main::{lambda(std::vector<int,std::allocator<int>>,int)#2}::operator() const((__int64)&v13,(__int64)&a5,(__int64)&v12,v5);std::vector<int,std::allocator<int>>::operator=(v8, &v13);std::vector<int,std::allocator<int>>::~vector(&v13);std::vector<int,std::allocator<int>>::~vector(&v12);__gnu_cxx::__normal_iterator<int *,std::vector<int,std::allocator<int>>>::operator++(&v10);}std::vector<int,std::allocator<int>>::vector(v11, v8);result = v11;v7 = *MK_FP(__FS__, 40LL) ^ v14;return result; }這個函數靜態分析了半天,直接沒看明白啥意思。。。
看了看其它大佬動態分析的結果,這個函數功能只是把經過 accumulate 函數后的結果. 把結果都記錄下來后. 發現只是把 transform函數后的結果進行了逆序.(稍后補充解析過程)我動調環境出了點問題。。
代碼實現
#include <stdio.h>int fib(int a) {if (!a || a == 1)return 1;return fib(a - 1) + fib(a - 2); }int main(void) {int flag[100] = { 0 }, i = 0;for (i = 0; i <= 15; i++){flag[i] = fib(i);}for (i = 15; i >= 0; i--){printf("%d ", flag[i] = (i < 15 ? flag[i] - flag[15] : flag[i]));}return 0; }[MRCTF2020]EasyCpp
for ( i = 0; i <= 8; ++i ){std::istream::operator>>(&std::cin, &keys[i]);// 輸入進行賦值std::__cxx11::to_string((std::__cxx11 *)v22, keys[i]);// keys每個元素賦值給v22std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::operator+=((__int64)v18, (__int64)v22);// 把每個元素字符串加起來,最后放進v18std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::~basic_string(v22);// 釋放掉v22}v28 = keys; // keys賦給v28v29 = keys; // keys賦給v29v27 = (int *)&unk_83E4; // 這里取出v27的作用也就是起到一個end作用while ( v29 != v27 ){v17 = *v29;std::vector<int>::push_back((__int64)v20, (__int64)&v17);// 這里就是把每個keys元素進行push++v29;}main::{lambda(int &)#1}
unsigned int v2; // ebx__int64 v3; // raxchar v5; // [rsp+Fh] [rbp-21h] BYREF__int64 v6; // [rsp+10h] [rbp-20h] BYREF__int64 v7[3]; // [rsp+18h] [rbp-18h] BYREFv7[0] = a1;v6 = a2;while ( (unsigned __int8)__gnu_cxx::operator!=<int *,std::vector<int>>(v7, &v6) ){v3 = __gnu_cxx::__normal_iterator<int *,std::vector<int>>::operator*(v7);main::{lambda(int &)#1}::operator()(&v5, v3);__gnu_cxx::__normal_iterator<int *,std::vector<int>>::operator++(v7);}return v2;lambda(int &)#1
_DWORD *result; // raxresult = a2;*a2 ^= 1u;return result;異或1然后返回
:operator++(_QWORD *a1)
*a1 += 4LL;return a1;這里的我剛開始以為是元素值自增4,但后來看了一下傳過來的參數v7是個地址,所以*a1也就是個地址,a1的話就是二級指針,查看匯編代碼驗證一下:
lea rdx, [rax+4] mov rax, [rbp+var_8] mov [rax], rdx mov rax, [rbp+var_8]這里用的是
總結
以上是生活随笔為你收集整理的XCTF easyCpp buu [MRCTF2020]EasyCpp的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: easyre-153 testre寒假
- 下一篇: *CTF MineGame