刮开有奖 首先使用Exeinfo PE检查是否有壳并确定是32位还是64位
有壳脱壳/无壳查看文件类型-使用32/64位ida打开
shift+F12进入字符串窗口 发现base64加密方式(确定flag部分用到base64解码)
返回main函数 F5查看
跟进查看DialogFunc参数
String设定长度为8位且下面if语句使用到String
找到可疑点 v4”ak1w“ 和 v5”V1Ax” (先用base64解码得到 v4”jMp” 和 v5”WP1”)
所以此时猜测flag为长为8的字符串
此时还有两个需注意函数 sub_4010F0 和 sub_401000
此时想解决if语句中String[0]的值,那就要先解决v7值为多少
于是跟进前面与v7有关的函数sub_4010F0(v7,0,10)
此函数传入v7-v16十个数 直接c语言实现一下sub_4010F0查看此函数的作用(算法分析)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 #include <stdlib.h> #include <stdio.h> int __cdecl sub_4010F0 (char *a1, int a2, int a3) { int result; int i; int v5; int v6; result = a3; for ( i = a2; i <= a3; a2 = i ) { v5 = i; v6 = i[a1]; if ( a2 < result && i < result ) { do { if ( v6 > a1[result] ) { if ( i >= result ) break ; ++i; a1[v5] = a1[result]; if ( i >= result ) break ; while ( a1[i] <= v6 ) { if ( ++i >= result ) goto LABEL_13; } if ( i >= result ) break ; v5 = i; a1[result] = a1[i]; } --result; } while ( i < result ); } LABEL_13: a1[result] = v6; sub_4010F0(a1, a2, i - 1 ); result = a3; ++i; } return result; }int main () { char str[20 ]={90 ,74 ,83 ,69 ,67 ,97 ,78 ,72 ,51 ,110 ,103 }; sub_4010F0(str,0 ,10 ); printf ("%s " ,str); return 0 ; }
运行得出
有理由得出sub_4010F0函数是一个排序函数 且由小到大 所以v7-v16十个数重新由小到大赋值
解得
String[0]=51+34=85//ascii=U
String[1]=//ascii=J
String[2]=3*69+141/4=87//ascii=W
String[3]=同String[2]=ascii=P
v4”jMp” 和 v5”WP1”
所有字符都已得出
还要再考虑字符的排序 最后得出flag
后面v4 v5 可以看到第三第四字符已经是WP了 说明 WP1在前 jMp在后
将他们拼接在一起得到 UJWP1jMp
flag{UJWP1jMp}
[GWCTF 2019]pyre pyc文件需用pyc反编译器反编译
寻找在线反编译器即可
将编译出来的py文件分析 然后进行逆向 写出对应脚本 得到flag
根据逻辑分析
num = ((input1[i] + i) % 128 + 128) % 128 #input1[i]中对应的值加上下标的值 模128(后面+128 %128无用)
code[i] = code[i] ^ code[i + 1] #code[i]与后一项进行 异或(同一位置上的数字相等则得0 同一位置上的数字相异则得1)
分析结束后用py编写脚本实现逆向操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 code = [ '\x1f' , '\x12' , '\x1d' , '(' , '0' , '4' , '\x01' , '\x06' , '\x14' , '4' , ',' , '\x1b' , 'U' , '?' , 'o' , '6' , '*' , ':' , '\x01' , 'D' , ';' , '%' , '\x13' ] n = len (code)for i in range (n-2 ,-1 ,-1 ): code[i] = chr (ord (code[i]) ^ ord (code[i+1 ]))for i in range (n): print (chr ((ord (code[i])-i) % 128 ), end = "" )
运行得到flag
flag{Just_Re_1s_Ha66y!}
迷宫/数独 迷宫思想:给出几个键位 一般是四个 来控制上下左右 并给出迷宫
^ 1 1 1 1
0 1 0 0 0
0 1 0 1 0
1 1 1 1 #
数独思想:给出数独表 并且函数里面可以分析得出行和列不能有同样值
flag长为10,输入范围为0-4(已知)
1 4 _ 2 3
3 0 _ 1 _
0 _ 2 3 _
_ 3 _ _ 0
4 2 _ _ 1
[网鼎杯 2020 青龙组]jocker 题目为jocker 后面做题要小心点
无壳 32位 ida32打开
shift+f12查看字符串
双击到please input you flag:(其实哪个都可以)
f5进入查看伪代码
main函数得出flag长度为24
进入wrong(Str)和omg(Str)函数:
先不着急分析代码 因为题目是jocker
继续查看main函数里面的encrypt()和finally()函数 发现encrypt打不开 finally没东西
encrypt显示40151D指令转换不成代码 可疑
找完main函数里面所有的函数 发现最开始的几个字符串还有两个没有找到 并且字符串所在的函数进不去 猜测很有可能真正的flag藏在encrypt函数里面
回到main函数 现在我们主要目标就是进入encrypt函数和finally函数
发现其与0x41进行了异或操作
从IDA View窗口找到相应位置(可以找到wrong和omg字符串的位置 此位置下面就是我们要找的for循环和异或操作的汇编指令)
记录标志位 转战od进行动态分析 dump出函数
(也可以利用ida进行动态分析 或者shift+f2 使用idc修复指令 可惜我不会)
可以看到 40181B异或了41h jle跳转到了401807 说明此范围是for循环
紧接着到了call指令 所以可以确定call指令进入的就是encrypt函数
记录标志位 1833
od32打开找到标志位1833 在此处设置断点
f8执行到此处
发现od在执行到此处时会停止
其实是运行到了scanf 需要我们输入字符串
这里一定要输入与flag等长的字符串 不然程序会自动停止退出
前面得到flag长为24 我们输入123456789012345678901234
f7步入jocker.4021D0中
这就是encrypt函数内部 而且我们从右下角发现剩余没找到的字符串 也更加证明了我们之前的猜想
使用插件->ollydumpex->dump process进行dump脱壳并保存成新的exe文件
(关于为什么到这一步进行dump 说实话我也不是很懂)
选择Get EIP as OEP并进行dump 获得新的exe文件 再用ida32打开
找到start函数并进入(因为没有找到main函数)
发现以前未发现的字符串 come here 说明我们的方向是对的
for循环的if语句解释为:将我们输入的a1与aHahahahaDoYouF[i]进行异或并判断等不等于v2
但是需要注意一点:for循环了19次 而我们的flag是24位长 再根据wp开始时寻找的字符串 出现过“i hide the last part” 说明flag还缺少一部分
先求解flag的第一部分:aHa[i]已知 v2[i](v2的值是unk_403040赋予的)也已知
接下来写脚本求解
1 2 3 4 5 6 aHa = "hahahaha_do_you_find_me?" v2 = [0x0e ,0x0d ,0x09 ,0x06 ,0x13 ,0x05 ,0x58 ,0x56 ,0x3e , 0x06 ,0x0c ,0x3c ,0x1f ,0x57 ,0x14 ,0x6b ,0x57 ,0x59 ,0x0d ]for i in range (19 ): print (chr (ord (aHa[i]) ^ v2[i]),end='' )
运行得到:
flag{d07abccf8a410c
接着我们去找剩下的flag
在start函数中我们X键对start使用交叉引用 进入第一个函数里面
发现这正是我们之前的main函数
接着我们进入finally函数 dump后变成了sub_40159A函数
v3=%tp&: 然后并没有其他可用信息了
接下来进行猜测:
flag的标准形式最后一位是 ‘} ’ 也就是说 v3的最后一位 ‘:’ 与一个数异或得到了 ‘}’
: ^ } = 71
1 print (ord (':' ) ^ ord ('}' ))
输出
71
我们可以假设 v3的所有位都与71进行了异或 编写脚本
1 2 3 4 v3 = "%tp&:" for i in range (5 ): print (chr (ord (v3[i]) ^ 71 ),end='' )
运行得到:
b37a}
将flag的两个部分拼接
flag{d07abccf8a410cb37a}
[2019红帽杯]childRE 无壳 64位 ida64打开
shift+f12寻找字符串
根据字符串的内容推测 得出的flag要经过md5加密才可以提交
进入main函数 找到输出flag字符串位置 从下往上分析
第一部分 对outputString取余数和商的结果已知 并且和其进行对比的字符串也已知
编写脚本:
1 2 3 4 5 6 7 8 9 10 11 str1 = '(_@4620!08!6_0*0442!@186%%0@3=66!!974*3234=&0^3&1@=&0908!6_0*&' str2 = '55565653255552225565565555243466334653663544426565555525555222' str3 = '1234567890-=!@#$%^&*()_+qwertyuiop[]QWERTYUIOP{}asdfghjkl;,ASDFGHJKL:"ZXCVBNM<>?zxcvbnm,./' name = '' for i in range (62 ): name += chr (str3.index(str1[i]) + str3.index(str2[i])*23 ) print ("outputString = " + name)
输出结果
outputString = private: char * __thiscall R0Pxx::My_Aut0_PWN(unsigned char *)
继续向上分析:
以下资料摘自:https://blog.csdn.net/liweigao01/article/details/78351464
C++ 编译器的函数名修饰规则
无论 __cdecl,__fastcall还是__stdcall调用方式,函数修饰都是以一个“?”開始,后面紧跟函数的名字。再后面是參数表的開始标识和 依照參数类型代号拼出的參数表。
知:outputString = ?My_Aut0_PWN
对于C++的类成员函数(其调用方式是__thiscall)。函数的名字修饰与非成员的C++函数稍有不同,首先就是在函数名字和參数表之间插入以“@”字 符引导的类名。
知:outputString = ?My_Aut0_PWN@R0Pxx
其次是參数表的開始标识不同,公有(public)成员函数的标识是“@@QAE”,保护(protected)成员函数的标识是 “@@IAE”,私有(private)成员函数的标识是“@@AAE”。
知:outputString = ?My_Aut0_PWN@R0Pxx@****@AAE
之后是添加參数,先填返回值类型參数,再添加函数形參
X–void
D–char
E–unsigned char
F–short
H–int
I–unsigned int
J–long
K–unsigned long(DWORD)
M–float
N–double
_N–bool
U–struct
….
指针的方式有些特别。用PA表示指针,用PB表示const类型的指针。
返回值类型为char 对应PAD
形参类型为unsigned char 对应PAE
知:outputString = ?My_Aut0_PWN@R0Pxx@@AAEPADPAE
參数表后以“@Z”标识整个名字的结束。假设该函数无參数,则 以“Z”标识结束。
知:outputString = ?My_Aut0_PWN@R0Pxx@****@AAEPADPAE@Z
继续向上分析:
if( v4 )里面我们无法得知进行了怎么的顺序重排 所以这时候需要进行动态调试:
此处设下断点
选择 Local Windows debugger
运行 输入一串长为31且互不相同的字符串
这里我使用的:qwertyuiopasdfghjklzxcvbnm12345
之后f7单步步入进去 找到与值对应的赋值命令 al里面的值便是我们所需要的(动调前可以根据字符串等来进行定位)
之后f8单步运行并记录下RAX中的31个字符(字符根据自己输入内容而改变 并不是完全不变)
得到打乱后顺序:
0x68,0x6a,0x69,0x6b,0x6c,0x6f,0x72,0x7a,0x78,0x70,0x63,0x76,0x61,0x74,0x77,0x62,0x6e,
0x73,0x6d,0x31,0x64,0x79,0x32,0x33,0x66,0x34,0x35,0x67,0x75,0x65,0x71
接下来编写脚本进行求解:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 flag = '?My_Aut0_PWN@R0Pxx@@AAEPADPAE@Z' a = 'qwertyuiopasdfghjklzxcvbnm12345' b = [0x68 ,0x6a ,0x69 ,0x6b ,0x6c ,0x6f ,0x72 ,0x7a ,0x78 ,0x70 ,0x63 , 0x76 ,0x61 ,0x74 ,0x77 ,0x62 ,0x6e ,0x73 ,0x6d ,0x31 ,0x64 ,0x79 , 0x32 ,0x33 ,0x66 ,0x34 ,0x35 ,0x67 ,0x75 ,0x65 ,0x71 ] B = '' c = [0 ]*31 d = [0 ]*31 for i in range (31 ): B += chr (b[i]) for i in range (31 ): c[i] = a.index(B[i]) d[c[i]] = flag[i] for i in range (31 ): print (d[i], end='' )
输出结果:
Z0@tRAEyuP@xAAA?M_A0_WNPx@@EPDP
最后进行MD5加密
flag{63b148e750fed3a33419168ac58083f5}
[2019红帽杯]easyRE 无壳 64位 ida64打开 elf文件
shift+f12进入字符串查找 找到与flag相关 进入函数
并且发现base64加密表 后面可能会进行解密
进入main函数分析:
查看其他wp时候 发现v15异或之后等于
the first four chars are ‘flag’
不过对我好像没有什么太大的影响
接着向下分析:
off_6CC090的值:
Vm0wd2VHUXhTWGhpUm1SWVYwZDRWVll3Wkc5WFJsbDNXa1pPVlUxV2NIcFhhMk0xVmpKS1NHVkdXbFpOYmtKVVZtcEtTMUl5VGtsaVJtUk9ZV3hhZVZadGVHdFRNVTVYVW01T2FGSnRVbGhhVjNoaFZWWmtWMXBFVWxSTmJFcElWbTAxVDJGV1NuTlhia0pXWWxob1dGUnJXbXRXTVZaeVdrWm9hVlpyV1hwV1IzaGhXVmRHVjFOdVVsWmlhMHBZV1ZSR1lWZEdVbFZTYlhSWFRWWndNRlZ0TVc5VWJGcFZWbXR3VjJKSFVYZFdha1pXWlZaT2NtRkhhRk5pVjJoWVYxZDBhMVV3TlhOalJscFlZbGhTY1ZsclduZGxiR1J5VmxSR1ZXSlZjRWhaTUZKaFZqSktWVkZZYUZkV1JWcFlWV3BHYTFkWFRrZFRiV3hvVFVoQ1dsWXhaRFJpTWtsM1RVaG9hbEpYYUhOVmJUVkRZekZhY1ZKcmRGTk5Wa3A2VjJ0U1ExWlhTbFpqUldoYVRVWndkbFpxUmtwbGJVWklZVVprYUdFeGNHOVhXSEJIWkRGS2RGSnJhR2hTYXpWdlZGVm9RMlJzV25STldHUlZUVlpXTlZadE5VOVdiVXBJVld4c1dtSllUWGhXTUZwell6RmFkRkpzVWxOaVNFSktWa1phVTFFeFduUlRhMlJxVWxad1YxWnRlRXRXTVZaSFVsUnNVVlZVTURrPQ==
对它进行十次base64解密
https://bbs.pediy.com/thread-254172.html
网站内容不错。。 就是没有flag
我在找off_6CC090字符串的时候 它下面有两个值我注意了一下 不过也没有放在心上
这时候回头来看 交叉引用找到所在函数
然后对函数名进行交叉引用发现来自.fini段
其解示为
此节区包含了可执行的指令,是进程终止代码的一部分。程序正常退出时,系统将安排执行这里的代码。
所以我们应该是找对了地方
开始着手分析:
补充两点:
1.byte_6CC0A0的长度为24
2.&v4+j = v4[j]
这里就是我前面说的 v15的值对我做这道题没有什么影响
编写脚本求解:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 byte_ = [0x40 ,0x35 ,0x20 ,0x56 ,0x5D ,0x18 ,0x22 ,0x45 ,0x17 ,0x2F , 0x24 ,0x6E ,0x62 ,0x3C ,0x27 ,0x54 ,0x48 ,0x6C ,0x24 ,0x6E , 0x72 ,0x3C ,0x32 ,0x45 ,0x5B ] STR = 'flag' v4 = '' flag = '' for i in range (4 ): v4 += chr (byte_[i] ^ ord (STR[i])) for i in range (len (byte_)): flag += chr (byte_[i] ^ ord (v4[i%4 ]))print (flag)
运行得到结果
flag{Act1ve_Defen5e_Test}
Youngter-drive 查壳 发现upx壳 32位
用upx脱壳工具 upx -d Youngter-drive.exe 脱完放进ida32打开
shift+f12打开字符串寻找main函数 留意
分析:
进入线程StartAddress进行查看
找到关键函数sub_41112C
进入 分析:
再进入另一个线程sub_41119F分析查看
也就是说 线程对字符串加密时只对奇数位加密 偶数位直接赋值
另外 我们现在还没有找到输出flag的字符
继续向下分析main函数:
接下来编写脚本:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 off_418004 = 'TOiZiZtOrYaToUwPnToBsOaOapsyS' off_418000 = 'QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm' flag = '' for i in range (29 ): if (i % 2 == 0 ): flag += off_418004[i] continue else : if (off_418004[i].isupper()): flag += chr (off_418000.index(off_418004[i]) + 96 ) else : flag += chr (off_418000.index(off_418004[i]) + 38 )print (flag)
运行得出
ThisisthreadofwindowshahaIsES
少了一位
网上的wp都没有很好的告诉最后一位怎么求 只是穷举
但有人说最后一位是什么都可以 BUU平台只认可E
不明白
flag{ThisisthreadofwindowshahaIsESE}
[2019红帽杯]Snake 第一次遇到 unity 和 .dll 文件处理
第一次使用pyhton的ctypes库
用dnSpy打开位于 \Snake_Data\Managed 的 Assembly-CSharp.dll 文件
unity在打包后,会将所有的代码打进一个Assembly-CSharp.dll的文件里面,通过这个文件的反编译,就是详细看见里面的代码内容。
找到这个(具体怎么找还在学ing)
其中对于GameObject解释:
ida64打开 Interface.dll
所在位置 \Snake_Data\Plugins
发现flag相关字符串 证明找对入口
接下来使用python的ctypes库进行爆破
脚本:
1 2 3 4 5 6 7 8 import ctypesfor i in range (100 ): dll = ctypes.cdll.LoadLibrary("\\Interface.dll" ) print (i) dll.GameObject(i)
flag{Ch4rp_W1th_R$@}
[羊城杯 2020]Bytecode python的bytecode 也就是字节码
反汇编指令功能可以从下面网站查找
dis — Python 字节码反汇编器 — Python 3.7.12 文档
原题目给的txt文档:
我尽量写的详细一点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 4 0 LOAD_CONST 0 (3 ) 3 LOAD_CONST 1 (37 ) 6 LOAD_CONST 2 (72 ) 9 LOAD_CONST 3 (9 ) 12 LOAD_CONST 4 (6 ) 15 LOAD_CONST 5 (132 ) 18 BUILD_LIST 6 21 STORE_NAME 0 (en) 5 24 LOAD_CONST 6 (101 ) 27 LOAD_CONST 7 (96 ) 30 LOAD_CONST 8 (23 ) 33 LOAD_CONST 9 (68 ) 36 LOAD_CONST 10 (112 ) 39 LOAD_CONST 11 (42 ) 42 LOAD_CONST 12 (107 ) 45 LOAD_CONST 13 (62 ) 48 LOAD_CONST 7 (96 ) 51 LOAD_CONST 14 (53 ) 54 LOAD_CONST 15 (176 ) 57 LOAD_CONST 16 (179 ) 60 LOAD_CONST 17 (98 ) 63 LOAD_CONST 14 (53 ) 66 LOAD_CONST 18 (67 ) 69 LOAD_CONST 19 (29 ) 72 LOAD_CONST 20 (41 ) 75 LOAD_CONST 21 (120 ) 78 LOAD_CONST 22 (60 ) 81 LOAD_CONST 23 (106 ) 84 LOAD_CONST 24 (51 ) 87 LOAD_CONST 6 (101 ) 90 LOAD_CONST 25 (178 ) 93 LOAD_CONST 26 (189 ) 96 LOAD_CONST 6 (101 ) 99 LOAD_CONST 27 (48 ) 102 BUILD_LIST 26 105 STORE_NAME 1 (output) 7 108 LOAD_CONST 28 ('welcome to GWHT2020' ) 111 PRINT_ITEM 112 PRINT_NEWLINE 9 113 LOAD_NAME 2 (raw_input) 116 LOAD_CONST 29 ('please input your flag:' ) 119 CALL_FUNCTION 1 122 STORE_NAME 3 (flag) 10 125 LOAD_NAME 3 (flag) 128 STORE_NAME 4 (str ) 12 131 LOAD_NAME 5 (len ) 134 LOAD_NAME 4 (str ) 137 CALL_FUNCTION 1 140 STORE_NAME 6 (a) 13 143 LOAD_NAME 6 (a) 146 LOAD_CONST 30 (38 ) 149 COMPARE_OP 0 (<) 152 POP_JUMP_IF_FALSE 173 14 155 LOAD_CONST 31 ('lenth wrong!' ) 158 PRINT_ITEM 159 PRINT_NEWLINE 15 160 LOAD_NAME 7 (exit) 163 LOAD_CONST 32 (0 ) 166 CALL_FUNCTION 1 169 POP_TOP 170 JUMP_FORWARD 0 (to 173 ) 17 >> 173 LOAD_NAME 8 (ord ) 176 LOAD_NAME 4 (str ) 179 LOAD_CONST 32 (0 ) 182 BINARY_SUBSCR 183 CALL_FUNCTION 1 186 LOAD_CONST 33 (2020 ) 189 BINARY_MULTIPLY 190 LOAD_NAME 8 (ord ) 193 LOAD_NAME 4 (str ) 196 LOAD_CONST 34 (1 ) 199 BINARY_SUBSCR 200 CALL_FUNCTION 1 203 BINARY_ADD 204 LOAD_CONST 33 (2020 ) 207 BINARY_MULTIPLY 208 LOAD_NAME 8 (ord ) 211 LOAD_NAME 4 (str ) 214 LOAD_CONST 35 (2 ) 217 BINARY_SUBSCR 218 CALL_FUNCTION 1 221 BINARY_ADD 222 LOAD_CONST 33 (2020 ) 225 BINARY_MULTIPLY 226 LOAD_NAME 8 (ord ) 229 LOAD_NAME 4 (str ) 232 LOAD_CONST 0 (3 ) 235 BINARY_SUBSCR 236 CALL_FUNCTION 1 239 BINARY_ADD 240 LOAD_CONST 33 (2020 ) 243 BINARY_MULTIPLY 244 LOAD_NAME 8 (ord ) 247 LOAD_NAME 4 (str ) 250 LOAD_CONST 36 (4 ) 253 BINARY_SUBSCR 254 CALL_FUNCTION 1 257 BINARY_ADD 258 LOAD_CONST 37 (1182843538814603 ) 261 COMPARE_OP 2 (==) 264 POP_JUMP_IF_FALSE 275 18 267 LOAD_CONST 38 ('good!continue\xe2\x80\xa6\xe2\x80\xa6' ) 270 PRINT_ITEM 271 PRINT_NEWLINE 272 JUMP_FORWARD 15 (to 290 )20 >> 275 LOAD_CONST 39 ('bye~' ) 278 PRINT_ITEM 279 PRINT_NEWLINE 21 280 LOAD_NAME 7 (exit) 283 LOAD_CONST 32 (0 ) 286 CALL_FUNCTION 1 289 POP_TOP 23 >> 290 BUILD_LIST 0 293 STORE_NAME 9 (x) 24 296 LOAD_CONST 40 (5 ) 299 STORE_NAME 10 (k)25 302 SETUP_LOOP 128 (to 433 ) 305 LOAD_NAME 11 (range ) 308 LOAD_CONST 41 (13 ) 311 CALL_FUNCTION 1 314 GET_ITER >> 315 FOR_ITER 114 (to 432 ) 318 STORE_NAME 12 (i) 26 321 LOAD_NAME 8 (ord ) 324 LOAD_NAME 4 (str ) 327 LOAD_NAME 10 (k) 330 BINARY_SUBSCR 331 CALL_FUNCTION 1 334 STORE_NAME 13 (b)27 337 LOAD_NAME 8 (ord ) 340 LOAD_NAME 4 (str ) 343 LOAD_NAME 10 (k) 346 LOAD_CONST 34 (1 ) 349 BINARY_ADD 350 BINARY_SUBSCR 351 CALL_FUNCTION 1 354 STORE_NAME 14 (c)28 357 LOAD_NAME 14 (c) 360 LOAD_NAME 0 (en) 363 LOAD_NAME 12 (i) 366 LOAD_CONST 4 (6 ) 369 BINARY_MODULO 370 BINARY_SUBSCR 371 BINARY_XOR 372 STORE_NAME 15 (a11) 29 375 LOAD_NAME 13 (b) 378 LOAD_NAME 0 (en) 381 LOAD_NAME 12 (i) 384 LOAD_CONST 4 (6 ) 387 BINARY_MODULO 388 BINARY_SUBSCR 389 BINARY_XOR 390 STORE_NAME 16 (a22)30 393 LOAD_NAME 9 (x) 396 LOAD_ATTR 17 (append) 399 LOAD_NAME 15 (a11) 402 CALL_FUNCTION 1 405 POP_TOP 31 406 LOAD_NAME 9 (x) 409 LOAD_ATTR 17 (append) 412 LOAD_NAME 16 (a22) 415 CALL_FUNCTION 1 418 POP_TOP 32 419 LOAD_NAME 10 (k) 422 LOAD_CONST 35 (2 ) 425 INPLACE_ADD 426 STORE_NAME 10 (k) 429 JUMP_ABSOLUTE 315 >> 432 POP_BLOCK 33 >> 433 LOAD_NAME 9 (x) 436 LOAD_NAME 1 (output) 439 COMPARE_OP 2 (==) 442 POP_JUMP_IF_FALSE 453 34 445 LOAD_CONST 38 ('good!continue\xe2\x80\xa6\xe2\x80\xa6' ) 448 PRINT_ITEM 449 PRINT_NEWLINE 450 JUMP_FORWARD 15 (to 468 )36 >> 453 LOAD_CONST 42 ('oh,you are wrong!' ) 456 PRINT_ITEM 457 PRINT_NEWLINE 37 458 LOAD_NAME 7 (exit) 461 LOAD_CONST 32 (0 ) 464 CALL_FUNCTION 1 467 POP_TOP 39 >> 468 LOAD_NAME 5 (len ) 471 LOAD_NAME 4 (str ) 474 CALL_FUNCTION 1 477 STORE_NAME 18 (l)40 480 LOAD_NAME 8 (ord ) 483 LOAD_NAME 4 (str ) 486 LOAD_NAME 18 (l) 489 LOAD_CONST 43 (7 ) 492 BINARY_SUBTRACT 493 BINARY_SUBSCR 494 CALL_FUNCTION 1 497 STORE_NAME 19 (a1) 41 500 LOAD_NAME 8 (ord ) 503 LOAD_NAME 4 (str ) 506 LOAD_NAME 18 (l) 509 LOAD_CONST 4 (6 ) 512 BINARY_SUBTRACT 513 BINARY_SUBSCR 514 CALL_FUNCTION 1 517 STORE_NAME 20 (a2)42 520 LOAD_NAME 8 (ord ) 523 LOAD_NAME 4 (str ) 526 LOAD_NAME 18 (l) 529 LOAD_CONST 40 (5 ) 532 BINARY_SUBTRACT 533 BINARY_SUBSCR 534 CALL_FUNCTION 1 537 STORE_NAME 21 (a3)43 540 LOAD_NAME 8 (ord ) 543 LOAD_NAME 4 (str ) 546 LOAD_NAME 18 (l) 549 LOAD_CONST 36 (4 ) 552 BINARY_SUBTRACT 553 BINARY_SUBSCR 554 CALL_FUNCTION 1 557 STORE_NAME 22 (a4)44 560 LOAD_NAME 8 (ord ) 563 LOAD_NAME 4 (str ) 566 LOAD_NAME 18 (l) 569 LOAD_CONST 0 (3 ) 572 BINARY_SUBTRACT 573 BINARY_SUBSCR 574 CALL_FUNCTION 1 577 STORE_NAME 23 (a5)45 580 LOAD_NAME 8 (ord ) 583 LOAD_NAME 4 (str ) 586 LOAD_NAME 18 (l) 589 LOAD_CONST 35 (2 ) 592 BINARY_SUBTRACT 593 BINARY_SUBSCR 594 CALL_FUNCTION 1 597 STORE_NAME 24 (a6)46 600 LOAD_NAME 19 (a1) 603 LOAD_CONST 0 (3 ) 606 BINARY_MULTIPLY 607 LOAD_NAME 20 (a2) 610 LOAD_CONST 35 (2 ) 613 BINARY_MULTIPLY 614 BINARY_ADD 615 LOAD_NAME 21 (a3) 618 LOAD_CONST 40 (5 ) 621 BINARY_MULTIPLY 622 BINARY_ADD 623 LOAD_CONST 44 (1003 ) 626 COMPARE_OP 2 (==) 629 POP_JUMP_IF_FALSE 807 47 632 LOAD_NAME 19 (a1) 635 LOAD_CONST 36 (4 ) 638 BINARY_MULTIPLY 639 LOAD_NAME 20 (a2) 642 LOAD_CONST 43 (7 ) 645 BINARY_MULTIPLY 646 BINARY_ADD 647 LOAD_NAME 21 (a3) 650 LOAD_CONST 3 (9 ) 653 BINARY_MULTIPLY 654 BINARY_ADD 655 LOAD_CONST 45 (2013 ) 658 COMPARE_OP 2 (==) 661 POP_JUMP_IF_FALSE 807 48 664 LOAD_NAME 19 (a1) 667 LOAD_NAME 20 (a2) 670 LOAD_CONST 46 (8 ) 673 BINARY_MULTIPLY 674 BINARY_ADD 675 LOAD_NAME 21 (a3) 678 LOAD_CONST 35 (2 ) 681 BINARY_MULTIPLY 682 BINARY_ADD 683 LOAD_CONST 47 (1109 ) 686 COMPARE_OP 2 (==) 689 POP_JUMP_IF_FALSE 804 49 692 LOAD_NAME 22 (a4) 695 LOAD_CONST 0 (3 ) 698 BINARY_MULTIPLY 699 LOAD_NAME 23 (a5) 702 LOAD_CONST 35 (2 ) 705 BINARY_MULTIPLY 706 BINARY_ADD 707 LOAD_NAME 24 (a6) 710 LOAD_CONST 40 (5 ) 713 BINARY_MULTIPLY 714 BINARY_ADD 715 LOAD_CONST 48 (671 ) 718 COMPARE_OP 2 (==) 721 POP_JUMP_IF_FALSE 801 50 724 LOAD_NAME 22 (a4) 727 LOAD_CONST 36 (4 ) 730 BINARY_MULTIPLY 731 LOAD_NAME 23 (a5) 734 LOAD_CONST 43 (7 ) 737 BINARY_MULTIPLY 738 BINARY_ADD 739 LOAD_NAME 24 (a6) 742 LOAD_CONST 3 (9 ) 745 BINARY_MULTIPLY 746 BINARY_ADD 747 LOAD_CONST 49 (1252 ) 750 COMPARE_OP 2 (==) 753 POP_JUMP_IF_FALSE 798 51 756 LOAD_NAME 22 (a4) 759 LOAD_NAME 23 (a5) 762 LOAD_CONST 46 (8 ) 765 BINARY_MULTIPLY 766 BINARY_ADD 767 LOAD_NAME 24 (a6) 770 LOAD_CONST 35 (2 ) 773 BINARY_MULTIPLY 774 BINARY_ADD 775 LOAD_CONST 50 (644 ) 778 COMPARE_OP 2 (==) 781 POP_JUMP_IF_FALSE 795 52 784 LOAD_CONST 51 ('congraduation!you get the right flag!' ) 787 PRINT_ITEM 788 PRINT_NEWLINE 789 JUMP_ABSOLUTE 795 792 JUMP_ABSOLUTE 798 >> 795 JUMP_ABSOLUTE 801 >> 798 JUMP_ABSOLUTE 804 >> 801 JUMP_ABSOLUTE 807 >> 804 JUMP_FORWARD 0 (to 807 ) >> 807 LOAD_CONST 52 (None ) 810 RETURN_VALUE
之后自己把python源码写出:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 en = [3 ,37 ,72 ,9 ,6 ,132 ] output = [101 ,96 ,23 ,68 ,112 ,42 ,107 ,62 ,96 ,53 ,176 ,179 ,98 ,53 ,67 ,29 ,41 ,120 ,60 ,106 ,51 ,101 ,178 ,189 ,101 ,48 ]print ('welcome to GWHT2020' ) flag = raw_input('please input your flag:' )str = flag a = len (str )if (a < 38 ): print ('lenth wrong!' ) exit(0 )if ((((ord (str [0 ]) * 2020 + ord (str [1 ])) * 2020 + ord (str [2 ])) * 2020 + ord (str [3 ])) * 2020 + ord (str [4 ]) == 1182843538814603 ): print ('good!continue\xe2\x80\xa6\xe2\x80\xa6' )else : print ('bye~' ) exit(0 ) x = [] k = 5 for i in range (13 ): b = ord (str [k]) c = ord (str [k+1 ]) a11 = c ^ en[i%6 ] a22 = b ^ en[i%6 ] x.append(a11) x.append(a22) k += 2 if (output == x): print ('good!continue\xe2\x80\xa6\xe2\x80\xa6' )else : print ('oh,you are wrong!' ) exit(0 ) l = len (str ) a1 = ord (str [l-7 ]) a2 = ord (str [l-6 ]) a3 = ord (str [l-5 ]) a4 = ord (str [l-4 ]) a5 = ord (str [l-3 ]) a6 = ord (str [l-2 ])if (a1 * 3 + a2 * 2 + a3 * 5 ) == 1003 : if (a1 * 4 + a2 * 7 + a3 * 9 ) == 2013 : if (a1 + a2 *8 + a3 *2 ) == 1109 : if (a4 * 3 + a5 * 2 + a6 * 5 ) == 671 : if (a4 * 4 + a5 * 7 + a6 * 9 ) == 1252 : if (a4 + a5 * 8 + a6 * 2 ) == 644 : print ('congraduation!you get the right flag!' )
如何边写边检验:
python的dis库
使用方法:
python3 -m dis xxxxxxx.py
这个题还没完 只是把源码解出 还没有解出flag
看到有多项式 直接z3一把梭
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 from z3 import * s = Solver() a1 = Int('a1' ) a2 = Int('a2' ) a3 = Int('a3' ) a4 = Int('a4' ) a5 = Int('a5' ) a6 = Int('a6' ) s.add(a1 * 3 + a2 * 2 + a3 * 5 == 1003 ) s.add(a1 * 4 + a2 * 7 + a3 * 9 == 2013 ) s.add(a1 + a2 *8 + a3 *2 == 1109 ) s.add(a4 * 3 + a5 * 2 + a6 * 5 == 671 ) s.add(a4 * 4 + a5 * 7 + a6 * 9 == 1252 ) s.add(a4 + a5 * 8 + a6 * 2 == 644 )if s.check() == sat: result = s.model() en = [3 ,37 ,72 ,9 ,6 ,132 ] output = [101 ,96 ,23 ,68 ,112 ,42 ,107 ,62 ,96 ,53 ,176 ,179 ,98 ,53 ,67 ,29 ,41 ,120 ,60 ,106 ,51 ,101 ,178 ,189 ,101 ,48 ] k = 0 flag = '' for i in range (13 ): flag += chr (output[k+1 ] ^ en[i%6 ]) flag += chr (output[k] ^ en[i%6 ]) k += 2 print (flag + chr (97 ) + chr (101 ) + chr (102 ) + chr (102 ) + chr (55 ) + chr (51 ))
flag{cfa2b87b3f746a8f0ac5c5963faeff73}
[NPUCTF2020]BasicASM 安利
[【逆向漫谈】关于汇编 | NPUCTF2020]BasicASM_哔哩哔哩_bilibili
这个题给了两个文件
一个是.s文件 内容如下 x86的汇编语言
另一个是运行后的输出结果
0x66,0x2e,0x61,0x25,0x7b,0x26,0x30,0x1d,0x79,0x72,0x75,0x1d,0x6b,0x2c,0x6f,0x35,0x5f,0x3a,0x38,0x74,0x2d,0x74,0x34,0x1d,0x61,0x77,0x6d,0x7d,0x7d
我尽量多写(抄)几行注释
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 00007FF7A8AC5A50 push rbp 00007FF7A8AC5A52 push rdi 00007FF7A8AC5A53 sub rsp,238h 00007FF7A8AC5A5A lea rbp,[rsp+20h] 00007FF7A8AC5A5F mov rdi,rsp 00007FF7A8AC5A62 mov ecx,8Eh 00007FF7A8AC5A67 mov eax,0CCCCCCCCh 00007FF7A8AC5A6C rep stos dword ptr [rdi] 00007FF7A8AC5A6E mov rax,qword ptr [__security_cookie (07FF7A8AD3018h)] 00007FF7A8AC5A75 xor rax,rbp 00007FF7A8AC5A78 mov qword ptr [rbp+208h],rax 00007FF7A8AC5A7F lea rcx,[__06A15900_ConsoleApplication@cpp (07FF7A8AD902Ah)] 00007FF7A8AC5A86 call __CheckForDebuggerJustMyCode (07FF7A8AC1122h) #反调试 00007FF7A8AC5A8B lea rdx,[string "flag{this_is_a_fake_flag}" (07FF7A8ACF450h)] #取假flag地址 00007FF7A8AC5A92 lea rcx,[flag] #flag地址 00007FF7A8AC5A96 call std::basic_string<char,std::char_traits<char>,std::allocator<char> >::basic_string<char,std::char_traits<char>,std::allocator<char> > (07FF7A8AC15E1h) 00007FF7A8AC5A9B nop 00007FF7A8AC5A9C mov dword ptr [p],0 00007FF7A8AC5AA3 mov dword ptr [rbp+64h],0 00007FF7A8AC5AAA jmp main+64h (07FF7A8AC5AB4h) #main函数开始位置 跳转 00007FF7A8AC5AAC mov eax,dword ptr [rbp+64h] 00007FF7A8AC5AAF inc eax 00007FF7A8AC5AB1 mov dword ptr [rbp+64h],eax 00007FF7A8AC5AB4 movsxd rax,dword ptr [rbp+64h] #main函数跳转到这里 取dword 00007FF7A8AC5AB8 mov qword ptr [rbp+1F8h],rax 00007FF7A8AC5ABF lea rcx,[flag] #取flag地址 00007FF7A8AC5AC3 call std::basic_string<char,std::char_traits<char>,std::allocator<char> >::length (07FF7A8AC122Bh) #求flag长度 00007FF7A8AC5AC8 mov rcx,qword ptr [rbp+1F8h] #rcx = qword[rbp+1F8h] 00007FF7A8AC5ACF cmp rcx,rax #比较长度 00007FF7A8AC5AD2 jae main+1B2h (07FF7A8AC5C02h) #可以看作不等于跳转到false 00007FF7A8AC5AD8 mov eax,dword ptr [rbp+64h] 00007FF7A8AC5ADB and eax,1 00007FF7A8AC5ADE cmp eax,1 #cmp判断是奇数位还是偶数位 #取奇数位 00007FF7A8AC5AE1 jne main+126h (07FF7A8AC5B76h) #非奇数位跳转 00007FF7A8AC5AE7 movsxd rax,dword ptr [rbp+64h] 00007FF7A8AC5AEB mov rdx,rax 00007FF7A8AC5AEE lea rcx,[flag] 00007FF7A8AC5AF2 call std::basic_string<char,std::char_traits<char>,std::allocator<char> >::operator[] (07FF7A8AC1442h) #构建一个以rcx为起始 以rax为偏移的数组 00007FF7A8AC5AF7 movsx eax,byte ptr [rax] 00007FF7A8AC5AFA xor eax,42h #全篇看下来只有这里一处运算 00007FF7A8AC5AFD mov dword ptr [p],eax #异或后的字符放进p 00007FF7A8AC5B00 mov dl,30h 00007FF7A8AC5B02 lea rcx,[rbp+144h] 00007FF7A8AC5B09 call std::setfill<char> (07FF7A8AC1046h) #输出 00007FF7A8AC5B0E mov qword ptr [rbp+1F8h],rax 00007FF7A8AC5B15 mov edx,2 00007FF7A8AC5B1A lea rcx,[rbp+168h] 00007FF7A8AC5B21 call std::setw (07FF7A8AC10D2h) 00007FF7A8AC5B26 mov qword ptr [rbp+200h],rax 00007FF7A8AC5B2D lea rdx,[std::hex (07FF7A8AC1488h)] #输出16进制 00007FF7A8AC5B34 mov rcx,qword ptr [__imp_std::cout (07FF7A8AD71C0h)] 00007FF7A8AC5B3B call qword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (07FF7A8AD7160h)] 00007FF7A8AC5B41 mov rcx,qword ptr [rbp+200h] 00007FF7A8AC5B48 mov rdx,rcx 00007FF7A8AC5B4B mov rcx,rax 00007FF7A8AC5B4E call std::operator<<<char,std::char_traits<char>,__int64> (07FF7A8AC12F8h) #输出 00007FF7A8AC5B53 mov rcx,qword ptr [rbp+1F8h] 00007FF7A8AC5B5A mov rdx,rcx 00007FF7A8AC5B5D mov rcx,rax 00007FF7A8AC5B60 call std::operator<<<char,std::char_traits<char>,char> (07FF7A8AC11A4h) 00007FF7A8AC5B65 mov edx,dword ptr [p] 00007FF7A8AC5B68 mov rcx,rax 00007FF7A8AC5B6B call qword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (07FF7A8AD7158h)] 00007FF7A8AC5B71 jmp main+1ADh (07FF7A8AC5BFDh) 00007FF7A8AC5B76 movsxd rax,dword ptr [rbp+64h] #偶数位没有变化 00007FF7A8AC5B7A mov rdx,rax 00007FF7A8AC5B7D lea rcx,[flag] 00007FF7A8AC5B81 call std::basic_string<char,std::char_traits<char>,std::allocator<char> >::operator[] (07FF7A8AC1442h) 00007FF7A8AC5B86 movsx eax,byte ptr [rax] 00007FF7A8AC5B89 mov dword ptr [p],eax 00007FF7A8AC5B8C mov dl,30h 00007FF7A8AC5B8E lea rcx,[rbp+194h] 00007FF7A8AC5B95 call std::setfill<char> (07FF7A8AC1046h) 00007FF7A8AC5B9A mov qword ptr [rbp+1F8h],rax 00007FF7A8AC5BA1 mov edx,2 00007FF7A8AC5BA6 lea rcx,[rbp+1B8h] 00007FF7A8AC5BAD call std::setw (07FF7A8AC10D2h) 00007FF7A8AC5BB2 mov qword ptr [rbp+200h],rax 00007FF7A8AC5BB9 lea rdx,[std::hex (07FF7A8AC1488h)] 00007FF7A8AC5BC0 mov rcx,qword ptr [__imp_std::cout (07FF7A8AD71C0h)] 00007FF7A8AC5BC7 call qword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (07FF7A8AD7160h)] 00007FF7A8AC5BCD mov rcx,qword ptr [rbp+200h] 00007FF7A8AC5BD4 mov rdx,rcx 00007FF7A8AC5BD7 mov rcx,rax 00007FF7A8AC5BDA call std::operator<<<char,std::char_traits<char>,__int64> (07FF7A8AC12F8h) 00007FF7A8AC5BDF mov rcx,qword ptr [rbp+1F8h] 00007FF7A8AC5BE6 mov rdx,rcx 00007FF7A8AC5BE9 mov rcx,rax 00007FF7A8AC5BEC call std::operator<<<char,std::char_traits<char>,char> (07FF7A8AC11A4h) 00007FF7A8AC5BF1 mov edx,dword ptr [p] 00007FF7A8AC5BF4 mov rcx,rax 00007FF7A8AC5BF7 call qword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (07FF7A8AD7158h)] 00007FF7A8AC5BFD jmp main+5Ch (07FF7A8AC5AACh) 00007FF7A8AC5C02 mov dword ptr [rbp+1E4h],0 00007FF7A8AC5C0C lea rcx,[flag] 00007FF7A8AC5C10 call std::basic_string<char,std::char_traits<char>,std::allocator<char> >::~basic_string<char,std::char_traits<char>,std::allocator<char> > (07FF7A8AC1302h) 00007FF7A8AC5C15 mov eax,dword ptr [rbp+1E4h] 00007FF7A8AC5C1B mov edi,eax 00007FF7A8AC5C1D lea rcx,[rbp-20h] 00007FF7A8AC5C21 lea rdx,[__xt_z+540h (07FF7A8ACEFE0h)] 00007FF7A8AC5C28 call _RTC_CheckStackVars (07FF7A8AC1596h) 00007FF7A8AC5C2D mov eax,edi 00007FF7A8AC5C2F mov rcx,qword ptr [rbp+208h] 00007FF7A8AC5C36 xor rcx,rbp 00007FF7A8AC5C39 call __security_check_cookie (07FF7A8AC1190h) 00007FF7A8AC5C3E lea rsp,[rbp+218h] 00007FF7A8AC5C45 pop rdi 00007FF7A8AC5C46 pop rbp 00007FF7A8AC5C47 ret
所以加密方法很简单
奇数位异或0x42 偶数位直接输出
另一种:
根据上面看到只有一处进行异或的运算
所以exp可以这么来写
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 res = [0x66 ,0x2e ,0x61 ,0x25 ,0x7b ,0x26 ,0x30 ,0x1d ,0x79 ,0x72 ,0x75 ,0x1d ,0x6b ,0x2c , 0x6f ,0x35 ,0x5f ,0x3a ,0x38 ,0x74 ,0x2d ,0x74 ,0x34 ,0x1d ,0x61 ,0x77 ,0x6d ,0x7d ,0x7d ] for i in range (1 ,len (res),2 ): res[i] ^= 0x42 for i in range (len (res)): print (chr (res[i]), end='' )
flag{d0_y0u_know_x86-64_a5m?}
[De1CTF2019]Re_Sign 脱壳: 查壳发现有upx壳
试了一下upx -d re_sign.exe 发现报错
正好自己也没有手动脱过upx壳 试一下
upx壳一般适用ESP脱壳大法
ESP 定律法 - CTF Wiki (ctf-wiki.org)
od32打开 发现程序没有自动断在pushad上下
(关于 pushad 和 popad 的详细解释可以点上面的wiki链接)
F9运行一下 找到了pushad
F8步过 留意ESP的值 发现变红
在ESP上设置硬件断点
F9跳到硬件断点位置 发现popad
断点下面有两个跳转 一个短的跳转和一个长的跳转
而我们所需要找的程序入口一般为 长跳转所指地址
所以程序的真正入口点在0x405012处
将程序dump出来 修改入口点
如果:
之后程序打不开 这时候要再修复程序的输入表
工具 ImportREC
打开进程 修改OEP
此时修改OEP所填是偏移地址
之后点击IAT自动搜索 获取导入表 然后查找无效dll
找到无效dll 右键剪切
之后修正转储 选择之前dump出来的文件
生成新的dump_.exe 文件 这就是我们所需要的了
分析: 下面开始分析脱壳后的程序:
ida打开 查找字符串 交叉引用找到加密部分:
图中部分代码依据个人习惯改了函数名
无奈只好动调 一步一步来 对比着ida反编译代码和汇编地址 用od一步步动调
od打开原exe文件 因为dump出来的和修复完之后的不能进行动调
od之前已经找到了esp
所以这里f9运行到 popad 后面的 cmp 指令
然后跳转到esp 也就是0x405012地址处
ida中起始地址为0x401000 所以在od中找到相同位置 f4运行到此处
首先来看第一个函数 od f8单步步过
运行到此处程序暂停 也就是说 sub_402BA0 也就是改名后 inputt 函数是一个检测输入的函数
我们随意输入一串字符 这里我输入
123456789abcedfg
接着我们运行到那个换表base64函数 即 sub_401233
(字符串查找时发现了base64原表 ctrl+x 交叉引用找到了改名后为 nonbase64 的函数)
运行过此函数之后发现我们的输入变成了
EP8hR3AlRhVcGD9MHDIeHd==
如果是正常的base64加密 那我们输入的字符串会变成
MTIzNDU2Nzg5YWJjZWRmZw==
所以可以确定里面是换表的base64加密
接下来就还有两大步
1.找base64换表之后的表
2.找check时候的判断是否相等的字符串
所以我们od重新载入 按照之前的方法来到 sub_401233函数 f7 步进
运行到大概这个位置前后 找到 ptr ss:[ebp-44]
(我也不会找位置)
找到变换后的表
0123456789QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm+/
之后进行第二步
老方法 在ida中找到改名后为 check 的函数 找到起始地址和终止地址
od重新载入
找到 0x401F0A 位置 f7步入函数
(猜测:check大多会在函数结束时候发生 也就是在终止地址前面不是很远)
其中这里面需要注意
我们运行到这里的时候 0x401FFC 是一个大跳转 如果直接运行下去 程序会自动退出
所以我们在它下面的位置设置新的运行点
一路f8 并且注意 cmp 指令 查看它的上一条 pop eax/ebx 或者是 push eax/ebx
上面就是我们需要进行对比的数据
0x08,0x3b,0x01,0x20,0x07,0x34,0x09,0x1f,0x18,0x24,0x13,0x03,0x10,0x38,0x09,0x1b,0x08,0x34,0x13,0x02,0x08,0x22,0x12,0x03,0x05,0x06,0x12,0x03,0x0f,0x22,0x12,0x17,0x08,0x01,0x29,0x22,0x06,0x24,0x32,0x24,0x0f,0x1f,0x2b,0x24,0x03,0x15,0x41,0x41
上面的数据最大是0x41 也就是65 最小是1
所以这里可以猜一下 动调出来的数据可能是对base64的原始表的排序
排序完的字符串再进行换表base64解密
先写exp试一下 (两个exp可以融合成一个的)
1 2 3 4 5 6 7 8 9 10 11 12 unk = [0x08 ,0x3b ,0x01 ,0x20 ,0x07 ,0x34 ,0x09 ,0x1f ,0x18 ,0x24 ,0x13 ,0x03 , 0x10 ,0x38 ,0x09 ,0x1b ,0x08 ,0x34 ,0x13 ,0x02 ,0x08 ,0x22 ,0x12 ,0x03 , 0x05 ,0x06 ,0x12 ,0x03 ,0x0f ,0x22 ,0x12 ,0x17 ,0x08 ,0x01 ,0x29 ,0x22 , 0x06 ,0x24 ,0x32 ,0x24 ,0x0f ,0x1f ,0x2b ,0x24 ,0x03 ,0x15 ,0x41 ,0x41 ] flag = '' base = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=' for i in unk: flag += base[i-1 ]print (flag)
输出:H6AfGzIeXjSCP3IaHzSBHhRCEFRCOhRWHAohFjxjOeqjCU==
1 2 3 4 5 6 7 8 9 10 import base64import string table = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" model = "0123456789QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm+/" flag = "H6AfGzIeXjSCP3IaHzSBHhRCEFRCOhRWHAohFjxjOeqjCU==" print (base64.b64decode(flag.translate(str .maketrans(model,table))))
输出结果正是flag
猜想成立
flag{E_L4nguag3_1s_K3KeK3_N4Ji4}