0x1 锁定目标  1.百度攻防世界:Reversing-x64Elf-100,1分题,应该没有难度吧
  2.老规矩,先查壳
  3.手上没有linux系统,但是简单的题应该用不上动态调试,靠IDA足够了。
0x2 静态分析  1.直接拖进IDA看看main函数,可以看到sub_4006FD函数是关键,它的返回值决定我们输入的flag是否正确:
复制代码 隐藏代码
__int64 __fastcall main(int a1, char **a2, char **a3){ __int64 result;
// rax char s[
264];
// [rsp+0h] [rbp-110h] BYREF unsigned __int64 v5;
// [rsp+108h] [rbp-8h] v5 = __readfsqword(
0x28u);
printf(
"Enter the password: ");
if ( !
fgets(s,
255, stdin) )
return 0LL;
if ( (
unsigned int)
sub_4006FD((__int64)s) ) {
puts(
"Incorrect password!"); result =
1LL; }
else {
puts(
"Nice!"); result =
0LL; }
return result;}
  2.再去看看sub_4006FD函数,通过main函数if条件我们知道这里必须返回true,也就是1:
复制代码 隐藏代码
__int64 __fastcall sub_4006FD(__int64 a1){
int i;
// [rsp+14h] [rbp-24h] __int64 v3[
4];
// [rsp+18h] [rbp-20h] v3[
0] = (__int64)
"Dufhbmf"; v3[
1] = (__int64)
"pG`imos"; v3[
2] = (__int64)
"ewUglpt";
for ( i =
0; i <=
11; ++i ) {
if ( *(
char *)(v3[i %
3] +
2 * (i /
3)) - *(
char *)(i + a1) !=
1 )
return 1LL; }
return 0LL;}
  3.有点懵,if只要成立一次就返回1???那我怎么知道完整的flag计算流程!!!
  4.vs 2015社区版一直自动退出,登录也登不上去,这下直接把代码拷贝过去运行的方法也没了。
  5.人工计算,大脑里运行一下,并记录结果:
for循环:
1)v3[0] + 0 - a1[0]!=1
2)v3[1] + 0 - a1[1]!=1
3)v3[2] + 0 - a1[2]!=1
==================================
1)v3[0] + 2 - a1[3]!=1
2)v3[1] + 2 - a1[4]!=1
3)v3[2] + 2 - a1[5]!=1
==================================
1)v3[0] + 4 - a1[6]!=1
2)v3[1] + 4 - a1[7]!=1
3)v3[2] + 4 - a1[8]!=1
==================================
1)v3[0] + 6 - a1[9]!=1
2)v3[1] + 6 - a1[10]!=1
3)v3[2] + 6 - a1[11]!=1
  6.共循环11次,最后结束循环,最终就是字符串Dpef'ubmlfst减去我们输入的字符串a1的值判断是否不等于1,如果不等于1,就返回1,也就是true。
  7.最后依靠百度,终于整明白了......,据说linux环境下函数执行成功返回0代表正确,非0代表错误,不知道对不对,但是这样理解这个代码就能看懂了。
  8.那么只要让每次if比较结果为真,也就是两个字符串相减等于1,最后循环结束后,返回0,代表true,成功。
  9.v3 -flag =1 ,代换过来就是flag = v3 - 1所以flag就是Dpef'ubmlfst - 1。
0x3 写脚本  1.这里我就不查表的一个个自己算了,你看看那个循环,算了老半天,不过收获,就是能看到那一行代码的意思了。
  2.看懂代码了,写脚本就好说,以前这种我就是复制到c++ ide工具里,颠倒一下计算过程赋值语句,不用看懂算法代码,跑一下就能得到flag。
  3.打开eclipse,编写java脚本:
1)因为java没有指针,但是学c语言的时候知道,数组就是指针
2)指针取值,这里用数组取值即可
3)字符串可以看做是一个char数组
  4.完整的代码:
复制代码 隐藏代码
package ctf;
public class test01 { public static void main(String[] args) {
int i;
//定义一个二维字符数组,把v3字符化 char[][] v3 =
new char[][] {{
'D',
'u',
'f',
'h',
'b',
'm',
'f'},{
'p',
'G',
'`',
'i',
'm',
'o',
's'},{
'e',
'w',
'U',
'g',
'l',
'p',
't'}}; StringBuffer flag =
new StringBuffer(
"");
for ( i =
0; i <=
11; ++i ) { flag.append((
char) (v3[i %
3][
2 * (i /
3)] -
1)) ;
//强制转换char类型,追加到字符串中 } System.out.println(
"flag:"+ flag); }}
输出:flag:Code_Talkers
  5.去验证一下,输入flag,成功截图:
0x4 总结  1.函数返回值那里把我给整懵了,浪费了不少的时间。
  2.vs2015社区版不知道啥原因,一打开就提示要登录,登录不上去,秒退,要不然这代码直接粘过去,都不用分析if里面那一行代码就能直接爆出flag。
使用道具 举报