[zctf 2016] reverse 100 write up

本文详细记录了解决编程挑战的过程,从初步分析输入密码的模式,到利用矩阵运算和Excel求解多元方程组,最终揭示隐藏的Flag。通过一步步深入的解析,不仅展现了解决问题的技巧,也体现了主办方的巧妙设计。
1. 首先跑跑程序,看看是个什么模式。发现输入了密码之后,啥都没有了,这样我们就不能从程序反馈找关键点了。从程序里面找找看。


2. 果然是第一道题,各种信息提示都有,好了,那么就可疑字符串进去看看吧。


3. 发现这个函数把这些话的空格去掉了,并且取前面的十六个字符。


4. 那么就看第一个函数。发现就是一个求解多元函数的解的方程组,直接用矩阵求解就好,这里还学习了一些用excel求解多元方程组。excel真是神奇。
具体如何用excel解方程组,百度一下就知道。
多元方程组的伪代码

int __cdecl main(int argc, const char **argv, const char **envp)
{
  signed int v3; // ebx@3
  int *v4; // ebp@3
  char *v5; // esi@3
  int v6; // edi@4
  signed int v7; // eax@4
  void *v8; // esi@8
  signed int v9; // edi@8
  int v10; // eax@8
  int v11; // ecx@11
  int v12; // eax@12
  int v14; // [sp+10h] [bp-690h]@3
  int v15; // [sp+14h] [bp-68Ch]@3
  int v16; // [sp+18h] [bp-688h]@3
  int v17; // [sp+1Ch] [bp-684h]@3
  int v18; // [sp+20h] [bp-680h]@3
  int v19; // [sp+24h] [bp-67Ch]@3
  int v20; // [sp+28h] [bp-678h]@3
  int v21; // [sp+2Ch] [bp-674h]@3
  int v22; // [sp+30h] [bp-670h]@3
  int v23; // [sp+34h] [bp-66Ch]@3
  int v24; // [sp+38h] [bp-668h]@3
  int v25; // [sp+3Ch] [bp-664h]@3
  int v26; // [sp+40h] [bp-660h]@3
  int v27; // [sp+44h] [bp-65Ch]@3
  int v28; // [sp+48h] [bp-658h]@3
  int v29; // [sp+4Ch] [bp-654h]@3
  char InputPassword[12]; // [sp+50h] [bp-650h]@1
  char v31; // [sp+60h] [bp-640h]@3
  char v32; // [sp+A3h] [bp-5FDh]@3
  char v33; // [sp+C3h] [bp-5DDh]@3
  char v34; // [sp+C4h] [bp-5DCh]@3
  __int16 v35; // [sp+DEh] [bp-5C2h]@3
  __int16 v36; // [sp+126h] [bp-57Ah]@3
  char v37; // [sp+128h] [bp-578h]@3
  __int16 v38; // [sp+162h] [bp-53Eh]@3
  __int16 v39; // [sp+18Ah] [bp-516h]@3
  char v40; // [sp+18Ch] [bp-514h]@3
  _BYTE v41[3]; // [sp+1C5h] [bp-4DBh]@3
  __int16 v42; // [sp+1EDh] [bp-4B3h]@3
  char v43; // [sp+1EFh] [bp-4B1h]@3
  char v44; // [sp+1F0h] [bp-4B0h]@3
  char v45; // [sp+22Bh] [bp-475h]@3
  char v46; // [sp+253h] [bp-44Dh]@3
  char v47; // [sp+254h] [bp-44Ch]@3
  int v48; // [sp+28Ch] [bp-414h]@3
  char v49; // [sp+2B8h] [bp-3E8h]@3
  int v50; // [sp+306h] [bp-39Ah]@3
  int v51; // [sp+30Ah] [bp-396h]@3
  int v52; // [sp+30Eh] [bp-392h]@3
  int v53; // [sp+312h] [bp-38Eh]@3
  int v54; // [sp+316h] [bp-38Ah]@3
  __int16 v55; // [sp+31Ah] [bp-386h]@3
  char v56; // [sp+31Ch] [bp-384h]@3
  int v57; // [sp+378h] [bp-328h]@3
  int v58; // [sp+37Ch] [bp-324h]@3
  char v59; // [sp+380h] [bp-320h]@3
  int v60; // [sp+3D1h] [bp-2CFh]@3
  int v61; // [sp+3D5h] [bp-2CBh]@3
  int v62; // [sp+3D9h] [bp-2C7h]@3
  int v63; // [sp+3DDh] [bp-2C3h]@3
  __int16 v64; // [sp+3E1h] [bp-2BFh]@3
  char v65; // [sp+3E3h] [bp-2BDh]@3
  char v66; // [sp+3E4h] [bp-2BCh]@3
  char v67; // [sp+40Bh] [bp-295h]@3
  char v68; // [sp+447h] [bp-259h]@3
  char v69; // [sp+448h] [bp-258h]@3
  __int16 v70; // [sp+482h] [bp-21Eh]@3
  __int16 v71; // [sp+4AAh] [bp-1F6h]@3
  char v72; // [sp+4ACh] [bp-1F4h]@3
  _BYTE v73[3]; // [sp+4EDh] [bp-1B3h]@3
  __int16 v74; // [sp+50Dh] [bp-193h]@3
  char v75; // [sp+50Fh] [bp-191h]@3
  char v76; // [sp+510h] [bp-190h]@3
  _BYTE v77[3]; // [sp+54Dh] [bp-153h]@3
  __int16 v78; // [sp+571h] [bp-12Fh]@3
  char v79; // [sp+573h] [bp-12Dh]@3
  char v80; // [sp+574h] [bp-12Ch]@3
  int v81; // [sp+5A8h] [bp-F8h]@3
  char v82; // [sp+5D8h] [bp-C8h]@3
  char v83; // [sp+623h] [bp-7Dh]@3
  char v84; // [sp+63Bh] [bp-65h]@3
  char v85; // [sp+63Ch] [bp-64h]@3
  _BYTE v86[3]; // [sp+67Dh] [bp-23h]@3
  __int16 v87; // [sp+69Dh] [bp-3h]@3
  char v88; // [sp+69Fh] [bp-1h]@3

  sub_401C00(&dword_4171C0, InputPassword);
  if ( strlen(InputPassword) != 16 )                #bigger than 16 chars 
    exit(0);
  qmemcpy(&v31, aMyDearForTheHu, 0x43u);
  memset(&v32, 0, 0x20u);
  v33 = 0;
  qmemcpy(&v34, aICannotChooseT, 0x1Au);
  memset(&v35, 0, 0x48u);
  v36 = 0;
  qmemcpy(&v37, aMyWishesAreFoo, 0x3Au);
  memset(&v38, 0, 0x28u);
  v39 = 0;
  qmemcpy(&v40, aWhatYouAreYouD, 0x39u);
  memset(v41, 0, 0x28u);
  v42 = 0;
  v43 = 0;
  qmemcpy(&v44, aDoNotSeatYourL, 0x3Bu);
  memset(&v45, 0, 0x28u);
  v46 = 0;
  qmemcpy(&v47, aDelusionsOfKno, 0x38u);
  memset(&v48, 0, 0x2Cu);
  qmemcpy(&v49, aListenMyHeartT, 0x4Eu);
  v50 = 0;
  v51 = 0;
  v52 = 0;
  v53 = 0;
  v54 = 0;
  v55 = 0;
  qmemcpy(&v56, aSomeUnseenFing, 0x5Cu);
  v57 = 0;
  v58 = 0;
  qmemcpy(&v59, aSorrowIsHushed, 0x51u);
  v60 = 0;
  v61 = 0;
  v62 = 0;
  v63 = 0;
  v64 = 0;
  v65 = 0;
  qmemcpy(&v66, aOnceWeDreamtTh, 0x27u);
  memset(&v67, 0, 0x3Cu);
  v68 = 0;
  qmemcpy(&v69, aHerWishfulFace, 0x3Au);
  memset(&v70, 0, 0x28u);
  v71 = 0;
  qmemcpy(&v72, aIfYouShedTears, 0x41u);
  memset(v73, 0, 0x20u);
  v74 = 0;
  v75 = 0;
  qmemcpy(&v76, aItIsTheTearsOf, 0x3Du);
  memset(v77, 0, 0x24u);
  v78 = 0;
  v79 = 0;
  qmemcpy(&v80, aThatIExistIsAP, 0x34u);
  memset(&v81, 0, 0x30u);
  qmemcpy(&v82, aGodExpectsAnsw, 0x4Bu);
  memset(&v83, 0, 0x18u);
  v84 = 0;
  qmemcpy(&v85, aOBeautyFindThy, 0x41u);
  memset(v86, 0, 0x20u);
  v87 = 0;
  v88 = 0;
  v14 = 179334;
  v15 = 175544;
  v16 = 180760;
  v17 = 182366;
  v18 = 182850;
  v19 = 180568;
  v20 = 181440;
  v21 = 178347;
  v22 = 181577;
  v23 = 176475;
  v24 = 174043;
  v25 = 179882;
  v26 = 178817;
  v27 = 175345;
  v28 = 178696;
  v29 = 175320;
  v3 = 0;
  v4 = &v14;
  v5 = &v31;<span style="white-space:pre">		</span><strong><span style="color:#ff0000;">#准备进行矩阵计算了---下面</span></strong>
  do
  {
    v6 = 0;
    sub_401000(v5);  <strong>#remove the space among the words</strong>
    v7 = 0;
    do
    {
      v6 += InputPassword[v7] * v5[v7];
      ++v7;
    }
    while ( v7 < 16 );
    if ( *v4 != v6 )
      exit(0);
    ++v3;
    v5 += 100; 
    ++v4;
  }
  while ( v3 < 16 );
  v8 = (void *)sub_402380(&unk_417130, aZctf_youAreAlm);
  sub_401820(v8, 0xAu);
  v9 = 0;
  v10 = (int)((char *)v8 + *(_DWORD *)(*(_DWORD *)v8 + 4));
  if ( !(*(_BYTE *)(v10 + 4) & 6)
    && (*(int (__thiscall **)(_DWORD))(**(_DWORD **)(v10 + 40) + 44))(*(_DWORD *)(v10 + 40)) == -1 )
    v9 = 4;
  v11 = (int)((char *)v8 + *(_DWORD *)(*(_DWORD *)v8 + 4));
  if ( v9 )
  {
    v12 = v9 | *(_DWORD *)(v11 + 4);
    if ( !*(_DWORD *)(v11 + 40) )
      LOBYTE(v12) = v12 | 4;
    std::ios_base::clear((std::ios_base *)v11, v12, 0);
  }
  return sub_401050(InputPassword);  <strong># check if you are really clever</strong>
}

用excel 求解,神奇的excel


根据这个方程组解出来的是flag"zctf{Wrong_Flag}". = =主办方真是爱开玩笑。


5. 再继续看,中间的处理看不是很懂,但是最后调用了一个函数“void __cdecl sub_401050(int inputPassword)”:
下面是伪代码。
void __cdecl sub_401050(int inputPassword)
{
  signed int v1; // eax@3
  signed int v2; // ecx@6
  int *v3; // esi@6
  int v4; // edx@7
  signed int i; // eax@7
  void *v6; // esi@11
  signed int v7; // edi@14
  int v8; // eax@14
  int v9; // ecx@17
  int v10; // eax@18
  char v11[16]; // [sp+Ch] [bp-64h]@1
  int v12; // [sp+20h] [bp-50h]@3
  int v13; // [sp+24h] [bp-4Ch]@3
  int v14; // [sp+28h] [bp-48h]@3
  int v15; // [sp+2Ch] [bp-44h]@3
  int v16; // [sp+30h] [bp-40h]@3
  int v17; // [sp+34h] [bp-3Ch]@3
  int v18; // [sp+38h] [bp-38h]@3
  int v19; // [sp+3Ch] [bp-34h]@3
  int v20; // [sp+40h] [bp-30h]@3
  int v21; // [sp+44h] [bp-2Ch]@3
  int v22; // [sp+48h] [bp-28h]@3
  int v23; // [sp+4Ch] [bp-24h]@3
  int v24; // [sp+50h] [bp-20h]@3
  int v25; // [sp+54h] [bp-1Ch]@3
  int v26; // [sp+58h] [bp-18h]@3
  int v27; // [sp+5Ch] [bp-14h]@3
  int v28; // [sp+60h] [bp-10h]@3
  int v29; // [sp+64h] [bp-Ch]@3
  int v30; // [sp+68h] [bp-8h]@3
  signed int v31; // [sp+6Ch] [bp-4h]@3

  inputPassword = *(_DWORD *)inputPassword;
  sub_401C00(&dword_4171C0, v11);             # continue input the password
  sub_401600(&unk_417130, strlen(v11));
  if ( strlen(v11) != 20 )
    exit(0);
  v16 = 562;
  v12 = 0;
  v13 = 0;
  v14 = 0;
  v15 = 0;
  v17 = 645;
  v18 = 756;
  v19 = 851;
  v20 = 920;
  v21 = 1017;
  v22 = 1132;
  v23 = 1253;
  v24 = 1348;
  v25 = 1427;
  v26 = 1531;
  v27 = 1626;
  v28 = 1697;
  v29 = 1808;
  v30 = 1908;
  v31 = 2033;
  v1 = 0;
  do
  {
    if ( v11[v1] != *((_BYTE *)&inputPassword + v1) ) # the v11[0:4] after prcess must equal the password'zctf'
      exit(0);
    ++v1;
  }
  while ( v1 < 4 );
  v2 = 5;
  v3 = &v16;
  do
  {
    v4 = 0;
    for ( i = 0; i < v2; ++i )  # pasword2[0:5].  the sum must be 562. which the [5] can be calculate
      v4 += v11[i];
    if ( *v3 != v4 )
      exit(0);
    ++v2;
    ++v3;
  }
  while ( v2 - 1 < 20 );
  v6 = (void *)sub_402380(&unk_417130, aZctf_youAreSoC);
  sub_401820(v6, 0xAu);
  v7 = 0;
  v8 = (int)((char *)v6 + *(_DWORD *)(*(_DWORD *)v6 + 4));
  if ( !(*(_BYTE *)(v8 + 4) & 6)
    && (*(int (__thiscall **)(_DWORD))(**(_DWORD **)(v8 + 40) + 44))(*(_DWORD *)(v8 + 40)) == -1 )
    v7 = 4;
  v9 = (int)((char *)v6 + *(_DWORD *)(*(_DWORD *)v6 + 4));
  if ( v7 )
  {
    v10 = v7 | *(_DWORD *)(v9 + 4);
    if ( !*(_DWORD *)(v9 + 40) )
      LOBYTE(v10) = v10 | 4;
    std::ios_base::clear((std::ios_base *)v9, v10, 0);
  }
}

6. 发现就是在保留了“zctf{”这几个字符的基础上,根据固定的数字列表,迭代求出来,很简单。


7.最终求得的就是flag“zctf{So_Easy_Oh_God}”。 感觉被主办方调戏了一把。= =。 so easy.


8. 完整的解析脚本。

s = ["My dear,for the hurt you sought to do me was is your good opinion.",
"I cannot choose the best.",
"My wishes are fools,they shout across thy song,my Master.",
"What you are you do not see,what you see is your shadow.",
"Do not seat your love upon a precipice because it is high.",
"Delusions of knowledge are like the fog of the morning.",
"Listen,my heart,to the whispers of the world with which it makes love to you.",
"Some unseen fingers,like an idle breeze,are playing upon my heart the music of the ripples.",
"Sorrow is hushed into peace in my heart like the evening among the silent trees.",
"Once we dreamt that we were strangers.",
"Her wishful face haunts my dreams like the rain at night.",
"If you shed tears when you miss the sun,you also miss the stars.",
"It is the tears of the earth that keep here smiles in bloom.",
"That I exist is a perpetual surprise which is life.",
"God expects answers for the flowers he sends us,not for the sun the earth.",
"O Beauty,find thyself in love,not in the flattery of thy mirror."
]


rS = []
MatrixA = []
MatrixB = [179334,175544,180760,182366,182850,180568,181440,178347,181577 \
    ,176475,174043,179882,178817,175345,178696,175320]

for i in range(len(s)):
    rS.append(s[i].replace(","," ").replace(".","").split(" "))
for i in range(len(rS)):
    tmps = list(''.join(rS[i])[:16])
    tmpsint = []
    for tmpstr in tmps:
        tmpsint.append(ord(tmpstr))
    MatrixA.append(tmpsint)
    # print tmpsint

# for i in range(len(MatrixA)):
#     for j in range(len(MatrixA[i])-1):
#         print str(MatrixA[i][j]) + "\t",
#     print str(MatrixA[i][len(MatrixA[i])-1])
# for Mb in MatrixB:
# 	print Mb
ans = [122,
99,
116,
102,
123,
87,
114,
111,
110,
103,
95,
70,
108,
97,
103,
125,
]
newans = []
nweint = []
for aa in ans:
	newans.append(chr(int(round(aa))))
print ''.join(newans)
print sum(ans[0:4])

Almost = [ 562,645,756,851,920,1017,1132,1253,1348,1427,1531,1626,1697,1808,1908,2033]
end = 5
start = ans[0:4]
theRest = []
for am in Almost:
	tt = am - sum(start) - sum(theRest)
	theRest.append(tt)
start.extend(theRest)
final = []
for tr in start:
	final.append(chr(tr))
print ''.join(final)


第一关还是简单, 后面的稍微看了一下,好久没弄逆向,对汇编不太熟练,发信ida要是不能够直接出伪代码,自己的速度就超级慢。
看来以后要加强自己这方面的软肋。
android的题目,到了so文件层面,对于一些直接爆出来的方法,比如,misc的最终要出来图片的方法,还是不熟。
目标赛棍going!
<think>好的,我现在需要回答用户关于在Ubuntu 24.04上检查GCC版本的问题。首先,我应该回忆一下常用的Linux命令。用户提到的是gcc version,所以直接使用gcc --version应该就能显示版本信息。这是最直接的方法,可能用户只需要这个命令。 不过,可能用户对系统其他信息也感兴趣,比如是否安装了多个版本的GCC或者如何切换版本。但根据问题,用户明确询问的是当前系统的GCC版本,所以先给出最简洁的答案比较好。此外,Ubuntu 24.04默认的GCC版本可能较新,比如GCC 13或更高,但具体需要实际查看。 另外,可能需要提到其他相关命令,比如使用dpkg来查询安装的软件包版本,或者查看/usr/bin/gcc的符号链接。但为了不过于复杂,先提供主要的方法,再在相关问题中扩展。 用户提供的引用中有关于Ubuntu安装CUDA和配置的内容,虽然与GCC版本无直接关联,但可能用户的环境涉及开发工具链,因此可以建议检查开发工具是否完整安装,比如build-essential包。不过这可能超出当前问题范围,但作为相关问题可以提到。 最后,生成的相关问题需要围绕GCC版本管理、安装其他版本、切换版本以及编译依赖等。确保问题有针对性,帮助用户进一步探索。</think>### 检查Ubuntu 24.04的GCC版本 #### 方法1:直接查看版本 在终端执行以下命令,可直接显示当前默认GCC版本: ```bash gcc --version ``` 输出示例: ``` gcc (Ubuntu 13.2.0-23ubuntu4) 13.2.0 Copyright (C) 2023 Free Software Foundation, Inc. ``` 此命令会显示GCC的主版本号(如13.2.0)和编译时间戳[^1]。 --- #### 方法2:查询软件包状态 通过`dpkg`工具查看已安装的GCC软件包详细信息: ```bash dpkg -l gcc ``` 输出示例: ``` ||/ 名称 版本 架构 描述 +++-==============-============-======-================================= ii gcc 4:13.2.0-1 amd64 GNU C编译器 ``` --- #### 方法3:检查符号链接 查看`/usr/bin/gcc`指向的实际二进制文件: ```bash ls -l /usr/bin/gcc ``` 输出示例: ``` lrwxrwxrwx 1 root root 5 Mar 30 14:22 /usr/bin/gcc -> gcc-13 ``` 此结果显示默认GCC指向`gcc-13`,即版本号为13[^2]。 --- #### 系统开发环境建议 如果输出提示`command not found`,说明未安装GCC。可通过以下命令安装: ```bash sudo apt update && sudo apt install build-essential ``` 该命令会安装GCC、G++、make等基础开发工具链[^3]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值