1.解题过程:
解压得到 rev300 文件,使用 32 位打开留意一下类型,发现又是 elf 类型的执行文件
使用Linux打开执行,拒绝访问
用 IDA 找到 main 函数反编译看看有什么东西
看到整体就只有一个 if 和 else 语句,可以看到 if 真时 put 的语句翻译为:允许访问
而 if 假时 put 的语句翻译为:拒绝访问,所以明确目标
使 if 为真的条件:a1>0,且 子函数 sub_8048414 返回值为真
并且 sub_8048414 传入了两个实参,对应的 (_BYTE *a1, int a2)
所以在函数 sub_8048414 内,*a1=a2[1],a2=0
查看子函数 sub_8048538
int __cdecl sub_8048538(int a1)
{int v2[33]; // [esp+18h] [ebp-A0h]int i; // [esp+9Ch] [ebp-1Ch]qmemcpy(v2, &unk_8048760, sizeof(v2));for ( i = 0; i <= 32; ++i )putchar(v2[i] ^ *(char *)(a1 + i % 8));return putchar(10);
}
这里的 qmemcpy 应该为 memcpy,v2 为 33 个元素的一维数组,同时我们可以从 (a1 + i % 8) 知道是随 i 增加历遍 a1,所以 a1 也应该为一维数组 0-8 八个元素,历遍四次,每个元素与 v2 的每一个元素异或并输出,所以此处输出的应该为 flag
查看 unk_8048760 并没有直接给我们,只能硬读,一个整型的元素占四个字节
.rodata:08048760 unk_8048760 db 0Fh ; DATA XREF: sub_8048538+12↑o
.rodata:08048761 db 0
.rodata:08048762 db 0
.rodata:08048763 db 0
.rodata:08048764 db 1Fh
.rodata:08048765 db 0
.rodata:08048766 db 0
.rodata:08048767 db 0
.rodata:08048768 db 4
.rodata:08048769 db 0
.rodata:0804876A db 0
.rodata:0804876B db 0
.rodata:0804876C db 9
.rodata:0804876D db 0
.rodata:0804876E db 0
.rodata:0804876F db 0
.rodata:08048770 db 1Ch
.rodata:08048771 db 0
.rodata:08048772 db 0
.rodata:08048773 db 0
.rodata:08048774 db 12h
.rodata:08048775 db 0
.rodata:08048776 db 0
.rodata:08048777 db 0
.rodata:08048778 db 42h ; B
.rodata:08048779 db 0
.rodata:0804877A db 0
.rodata:0804877B db 0
.rodata:0804877C db 9
.rodata:0804877D db 0
.rodata:0804877E db 0
.rodata:0804877F db 0
.rodata:08048780 db 0Ch
.rodata:08048781 db 0
.rodata:08048782 db 0
.rodata:08048783 db 0
.rodata:08048784 db 44h ; D
.rodata:08048785 db 0
.rodata:08048786 db 0
.rodata:08048787 db 0
.rodata:08048788 db 0Dh
.rodata:08048789 db 0
.rodata:0804878A db 0
.rodata:0804878B db 0
.rodata:0804878C db 7
.rodata:0804878D db 0
.rodata:0804878E db 0
.rodata:0804878F db 0
.rodata:08048790 db 9
.rodata:08048791 db 0
.rodata:08048792 db 0
.rodata:08048793 db 0
.rodata:08048794 db 6
.rodata:08048795 db 0
.rodata:08048796 db 0
.rodata:08048797 db 0
.rodata:08048798 db 2Dh ; -
.rodata:08048799 db 0
.rodata:0804879A db 0
.rodata:0804879B db 0
.rodata:0804879C db 37h ; 7
.rodata:0804879D db 0
.rodata:0804879E db 0
.rodata:0804879F db 0
.rodata:080487A0 db 59h ; Y
.rodata:080487A1 db 0
.rodata:080487A2 db 0
.rodata:080487A3 db 0
.rodata:080487A4 db 1Eh
.rodata:080487A5 db 0
.rodata:080487A6 db 0
.rodata:080487A7 db 0
.rodata:080487A8 db 0
.rodata:080487A9 db 0
.rodata:080487AA db 0
.rodata:080487AB db 0
.rodata:080487AC db 59h ; Y
.rodata:080487AD db 0
.rodata:080487AE db 0
.rodata:080487AF db 0
.rodata:080487B0 db 0Fh
.rodata:080487B1 db 0
.rodata:080487B2 db 0
.rodata:080487B3 db 0
.rodata:080487B4 db 8
.rodata:080487B5 db 0
.rodata:080487B6 db 0
.rodata:080487B7 db 0
.rodata:080487B8 db 1Ch
.rodata:080487B9 db 0
.rodata:080487BA db 0
.rodata:080487BB db 0
.rodata:080487BC db 23h ; #
.rodata:080487BD db 0
.rodata:080487BE db 0
.rodata:080487BF db 0
.rodata:080487C0 db 36h ; 6
.rodata:080487C1 db 0
.rodata:080487C2 db 0
.rodata:080487C3 db 0
.rodata:080487C4 db 7
.rodata:080487C5 db 0
.rodata:080487C6 db 0
.rodata:080487C7 db 0
.rodata:080487C8 db 55h ; U
.rodata:080487C9 db 0
.rodata:080487CA db 0
.rodata:080487CB db 0
.rodata:080487CC db 2
.rodata:080487CD db 0
.rodata:080487CE db 0
.rodata:080487CF db 0
.rodata:080487D0 db 0Ch
.rodata:080487D1 db 0
.rodata:080487D2 db 0
.rodata:080487D3 db 0
.rodata:080487D4 db 8
.rodata:080487D5 db 0
.rodata:080487D6 db 0
.rodata:080487D7 db 0
.rodata:080487D8 db 41h ; A
.rodata:080487D9 db 0
.rodata:080487DA db 0
.rodata:080487DB db 0
.rodata:080487DC db 0Ah
.rodata:080487DD db 0
.rodata:080487DE db 0
.rodata:080487DF db 0
.rodata:080487E0 db 14h
.rodata:080487E1 db 0
.rodata:080487E2 db 0
.rodata:080487E3 db 0
读完得到 unk_8048760 即得到数组 v2 的内容,现在缺少 a1
v2[33]={0x0F,0x1F,0x04,0x09,0x1C,0x12,0x42,0x09,0x0C,0x44,0x0D,0x07,0x09,0x06,0x2D,0x37,0x59,0x1E,0x00,0x59,0x0F,0x08,0x1C,0x23,0x36,0x07,0x55,0x02,0x0C,0x08,0x41,0x0A,0x14}
查看子函数 sub_8048414
发现了 a1,分析代码,当 if 为真,跳转 LABEL_19 ,接着对照代码继续分析
signed int __cdecl sub_8048414(_BYTE *a1, int a2)
{signed int result; // eaxswitch ( a2 ){case 0:if ( *a1 == 105 )goto LABEL_19;result = 0;break;case 1:if ( *a1 == 101 )goto LABEL_19;result = 0;break;case 3:if ( *a1 == 110 )goto LABEL_19;result = 0;break;case 4:if ( *a1 == 100 )goto LABEL_19;result = 0;break;case 5:if ( *a1 == 97 )goto LABEL_19;result = 0;break;case 6:if ( *a1 == 103 )goto LABEL_19;result = 0;break;case 7:if ( *a1 == 115 )goto LABEL_19;result = 0;break;case 9:if ( *a1 == 114 )
LABEL_19:result = sub_8048414(a1 + 1, 7 * (a2 + 1) % 11);elseresult = 0;break;default:result = 1;break;}return result;
}
在最后面的 LABEL_19 中可以看到,每次判断后都会将 *a1 = a1+1,a2 = 7 * (a2 + 1 % 11)
所以我们最后得到了一维数组 a1[8] = {105,115,101,110,103,97,114,100}
最后写 python 脚本将输出语句的 flag 跑出来
注意:python 中的数组表示不需要下标,元素使用 " [ ] " 而不是 “ { } ”
2.知识点:
(1)本题IDA中的涉及主要的假名字:
unk_ 未处理字节
IDA调试技巧(妥妥的干货分享) - 简书 (jianshu.com)
(2)涉及的 c 库函数:(v2[33])
memcpy(v2, &unk_8048760, sizeof(v2))
作用:从 unk_8048760 储存中复制33个字节到 v2 中
(3)0x是16进制的前缀,h是16进制的后缀