<think>我们分析给定的汇编代码,主要关注main函数和相关的数据段(特别是.rodata段中的数组)。目标是理解程序功能,尤其是如何验证用户输入的flag。
首先,观察main函数的结构:
1. 函数开头设置栈帧和保护机制(endbr64, push rbp, mov rbp, rsp, sub rsp, 40h, 栈溢出保护fs:28h)
2. 打印提示信息:"please input your flag"
3. 使用scanf读取用户输入到栈上的缓冲区[rbp-30h](注意:格式为"%s",可能存在缓冲区溢出风险,但这里缓冲区大小为0x30h?)
4. 将输入缓冲区的地址存入[rbp-38h],并初始化计数器[rbp-3Ch]为0
5. 进入循环:循环条件为计数器<=4,即循环5次(0,1,2,3,4)
6. 在循环体内:
- 从[rbp-38h]取出当前指针(指向输入字符串的某个位置),读取4字节(mov eax, [rax])到eax
- 根据计数器的值(edx)乘以4,从数组array中取出对应元素(array在.rodata:0000000000002010)
- 将取出的数组元素与0x12345678进行异或
- 比较eax和异或后的值,如果不相等则跳转到错误处理(打印"wrong!"并退出)
- 如果相等,则更新指针(加4,即下一个4字节)和计数器(加1)
7. 循环结束后,打印"you are right"
关键点:
- 用户输入的flag被当作一个32位整数(4字节)的数组来处理,每次比较4字节。
- 循环5次,所以总共比较5*4=20个字节。
- 数组array位于.rodata:0000000000002010,从代码中可以看到数组内容:
array: db 1Eh, 3Ah, 55h, 75h, 03h, 3Ah, 58h, 7Bh, 0Ch, 22h, 58h, 4Dh, 3Dh, 38h, 50h, 7Bh, 19h, 38h, 6Bh, 73h
注意:代码中每次取一个32位整数(4字节),以小端方式存储。
我们按照代码中的方式重新组织数组数据(每4字节一个小端整数):
第一个整数:0x75553A1E (因为小端:地址2010~2013:1E 3A 55 75 -> 0x75553A1E)
第二个整数:0x7B583A03 (地址2014~2017:03 3A 58 7B -> 0x7B583A03)
第三个整数:0x4D58220C (地址2018~201B:0C 22 58 4D -> 0x4D58220C)
第四个整数:0x7B50383D (地址201C~201F:3D 38 50 7B -> 0x7B50383D)
第五个整数:0x736B3819 (地址2020~2023:19 38 6B 73 -> 0x736B3819)
代码中对每个数组元素进行异或操作:异或的值是0x12345678
因此,正确的输入应该是:
整数1 = 0x75553A1E ^ 0x12345678 -> 0x67616C66
整数2 = 0x7B583A03 ^ 0x12345678 -> 0x696D615F
整数3 = 0x4D58220C ^ 0x12345678 -> 0x5F677265
整数4 = 0x7B50383D ^ 0x12345678 -> 0x696C6F63
整数5 = 0x736B3819 ^ 0x12345678 -> 0x61746500 (注意:最后有0)
将整数转换为小端字节序的字符串(注意:整数在内存中是按小端存储,但转换为字符串要按字节顺序):
整数1: 0x67,0x61,0x6C,0x66 -> 按字节顺序:0x66,0x6C,0x61,0x67 -> "flag"
整数2: 0x69,0x6D,0x61,0x5F -> 0x5F,0x61,0x6D,0x69 -> "_ami"
整数3: 0x5F,0x67,0x72,0x65 -> 0x65,0x72,0x67,0x5F -> "erg_"
整数4: 0x69,0x6C,0x6F,0x63 -> 0x63,0x6F,0x6C,0x69 -> "colo"
整数5: 0x61,0x74,0x65,0x00 -> 0x00,0x65,0x74,0x61 -> 注意:最后一个字节为0,所以是"ate\0"
但这样直接拼接得到:flag_ami_erg_coloate\0,显然不对。
我们需要重新考虑:在内存中,这些整数是连续存放的,所以整个字符串应该是:
整数1: 0x66,0x6C,0x61,0x67 -> "flag"
整数2: 0x5F,0x61,0x6D,0x69 -> "_ami"
整数3: 0x65,0x72,0x67,0x5F -> "erg_"
整数4: 0x63,0x6F,0x6C,0x69 -> "coli" (注意:这里应该是"lico",因为小端,但实际上我们得到的是0x696C6F63,所以字节序为:63 6F 6C 69 -> 0x63->'c',0x6F->'o',0x6C->'l',0x69->'i',所以是"coli"?)
实际上,我们按照小端序来解读每个整数:
整数1: 0x66,0x6C,0x61,0x67 -> 字符串:'f','l','a','g' -> "flag"
整数2: 0x5F,0x61,0x6D,0x69 -> 字符串:'_','a','m','i' -> "_ami"
整数3: 0x65,0x72,0x67,0x5F -> 字符串:'e','r','g','_' -> "erg_"
整数4: 0x63,0x6F,0x6C,0x69 -> 字符串:'c','o','l','i' -> "coli"
整数5: 0x00,0x65,0x74,0x61 -> 字符串:'\0','e','t','a' -> 但这样最后一个是0,所以字符串终止。
拼接起来:"flag_ami_erg_coli" 但是最后还有"eta"被截断了(因为0终止符)。这显然不合理。
重新检查计算:
整数1:0x75553A1E ^ 0x12345678 = 0x67616C66 -> 按字节:66 6C 61 67 -> "flag"
整数2:0x7B583A03 ^ 0x12345678 = 0x696C615F -> 按字节:5F 61 6C 69 -> 但实际上我们计算:
0x7B583A03 XOR 0x12345678:
7B583A03
XOR 12345678
= 696C6C7B ??? 不对,之前算错了吗?
重新计算:
0x7B583A03 ^ 0x12345678:
7B ^ 12 = 69
58 ^ 34 = 6C
3A ^ 56 = 6C
03 ^ 78 = 7B
所以整数2应该是0x696C6C7B -> 小端:7B 6C 6C 69 -> 字符串:'{','l','l','i' -> 这也不对。
注意:代码中取数组元素是32位整数,所以应该用小端方式读取数组中的原始数据,然后进行异或。
数组原始数据(小端):
第一个整数:0x75553A1E (内存顺序:1E 3A 55 75) -> 异或0x12345678(注意:异或操作也是按32位进行)
计算:0x75553A1E XOR 0x12345678 =
1E XOR 78 -> 66
3A XOR 56 -> 6C
55 XOR 34 -> 61
75 XOR 12 -> 67
所以结果是:0x67616C66 -> 小端解释为字符串:66 6C 61 67 -> "flag"
第二个整数:原始值0x7B583A03(内存顺序:03 3A 58 7B) -> 异或0x12345678:
03 XOR 78 = 7B
3A XOR 56 = 6C
58 XOR 34 = 6C
7B XOR 12 = 69
所以结果是0x696C6C7B -> 字符串:7B 6C 6C 69 -> 对应的ASCII:'{','l','l','i'
这显然不对,因为期望是"flag{...}"
重新检查数组数据:
.rodata:0000000000002010 array db 1Eh, 3Ah, 55h, 75h, 03h, 3Ah, 58h, 7Bh, 0Ch, 22h, 58h, 4Dh, 3Dh, 38h, 50h, 7Bh, 19h, 38h, 6Bh, 73h
我们之前划分整数时,每4个字节一个整数:
第一整数:75 55 3A 1E -> 注意:在内存中,地址2010是1E,2011是3A,2012是55,2013是75 -> 所以整数值应该是0x75553A1E(大端表示),但x86是小端,所以从内存加载到寄存器时,这个值就是0x75553A1E(因为小端:低地址是低字节,所以寄存器中:eax = [2010]=1E, [2011]=3A, [2012]=55, [2013]=75 -> 组合成0x75553A1E)
因此,我们不需要转换,直接使用这个整数进行异或。
但是,我们期望的flag是"flag{...}",所以我们重新计算:
整数1: 0x75553A1E XOR 0x12345678 = 0x67616C66 -> 对应字符串(小端顺序)"f","l","a","g" -> "flag"
整数2: 0x7B583A03 XOR 0x12345678 = 0x696C6C7B -> 对应字符串(小端顺序)"{","l","l","i" -> 但期望是"{"
这里发现,整数2的结果按小端顺序的第一个字节是0x7B,即'{',所以整个字符串应该是:
"flag" + "{" + ...
但是,整数2的另外三个字节是0x6C,0x6C,0x69,即"lli",所以整数2对应的部分是"{lli"?
继续计算整数3:
原始值:0x4D58220C (注意:数组接下来4字节:0Ch,22h,58h,4Dh -> 整数值0x4D58220C)
0x4D58220C XOR 0x12345678 =
0C XOR 78 -> 74
22 XOR 56 -> 74
58 XOR 34 -> 6C
4D XOR 12 -> 5F
结果为0x5F6C7474 -> 小端:74 74 6C 5F -> "ttl_" -> 这也不对。
重新审视程序:在循环中,每次从输入缓冲区取4个字节(作为一个整数)与array中对应的一个整数(异或0x12345678)进行比较。
因此,用户输入的字符串应该是20个字节(5*4),并且每4个字节按小端组成一个整数。
那么,如果用户输入的是"flag{......}",那么前4个字节是"f","l","a","g",对应的整数(小端)是0x67616C66(因为'f'=0x66, 'l'=0x6C, 'a'=0x61, 'g'=0x67,在内存中存储为:66 6C 61 67,转为32位整数就是0x67616C66)。
所以,array的第一个整数应该是0x67616C66 XOR 0x12345678 = 0x75553A1E,这与数组中的第一个整数0x75553A1E符合。
同理,接下来的4个字节应该是'{','l','l','i'吗?显然我们不希望是'{lli',我们希望下一个字符是其他内容。
实际上,程序验证的整个flag字符串应该是20个字节,包括最后的结束符?但是最后整数5有0,所以实际长度是19个字节(加上结束符0,共20字节?)
重新计算整数2:我们期望的第二个4字节是什么?
根据数组值0x7B583A03,异或0x12345678后应该是我们输入的第二组整数。
设第二组整数为X,则:X = 0x7B583A03 ^ 0x12345678 = 0x696C6C7B
0x696C6C7B按小端存储的字节:7B 6C 6C 69 -> 即字符:7B->'{', 6C->'l', 6C->'l', 69->'i'
所以第二个4字节就是"{lli"?这显然不是我们想要的。
但是,注意:我们计算的整数2的值为0x696C6C7B,而程序期望输入的就是0x696C6C7B(即用户输入的第二组整数应该是0x696C6C7B,对应字符串为"{lli")。
继续整数3:0x4D58220C ^ 0x12345678 = 0x5F6C7474 -> 按小端:74746C5F -> 字符串:"ttl_" -> 那么第三组输入就是"ttl_"
整数4:0x7B50383D ^ 0x12345678 = 0x69646E45 -> 小端:45 6E 64 69 -> 字符:'E','n','d','i' -> "Endi"(因为0x45='E',0x6E='n',0x64='d',0x69='i')
整数5:0x736B3819 ^ 0x12345678 = 0x615F6E61 -> 小端:61 6E 5F 61 -> 字符:'a','n','_','a' -> "an_a"
最后,我们得到整个字符串:
第一组4字节:"flag"
第二组4字节:"{lli"
第三组4字节:"ttl_"
第四组4字节:"Endi"
第五组4字节:"an_a"
拼接:"flag{llittl_Endian_a" -> 显然不合理。
注意:整数5的结果0x615F6E61,小端解析后是:61 6E 5F 61 -> 即"an_a",但第五组有20个字节?最后并没有结束符0。
但是,我们在数组中没有看到最后有0。注意,整数5的原始值0x736B3819 ^ 0x12345678 = 0x615F6E61,所以输入的最后4字节就是"an_a"。
整个字符串就是20个字节:flag{llittl_Endian_a
但是,我们期望的flag可能是"flag{little_Endian_flag}"之类的。
重新检查:可能是因为我们分组错误?实际上,整个字符串应该是连续的,但是按照4字节一组分组,并且每个分组内是小端序,这会导致字符串的字符顺序被打乱。
实际上,正确的做法是:将整个输入字符串看作一个字节数组,但是程序每次取4个字节(作为一个32位整数)进行比较。而数组array中存储的是经过异或后的整数,所以我们需要将正确的整数异或回来,然后按字节拆分,并按顺序排列。
但是,注意:程序在比较时,将输入的4个字节作为一个整数(小端),与array[i]异或0x12345678的值进行比较。
因此,如果我们想要得到正确的输入,应该:
设正确的输入为20个字节:B0, B1, B2, B3, B4, B5, ... , B18, B19
第一组4字节(B0,B1,B2,B3)组成小端整数:I0 = B0 + (B1<<8) + (B2<<16) + (B3<<24)
第二组4字节(B4,B5,B6,B7)组成:I1 = B4 + (B5<<8) + (B6<<16) + (B7<<24)
以此类推。
程序要求:I0 == array[0] ^ 0x12345678
I1 == array[1] ^ 0x12345678
...
所以:
I0 = 0x75553A1E ^ 0x12345678 = 0x67616C66
I1 = 0x7B583A03 ^ 0x12345678 = 0x696C6C7B
I2 = 0x4D58220C ^ 0x12345678 = 0x5F6C7474
I3 = 0x7B50383D ^ 0x12345678 = 0x69646E45
I4 = 0x736B3819 ^ 0x12345678 = 0x615F6E61
然后,我们将每个整数拆分为4个字节(小端顺序):
I0: 0x66, 0x6C, 0x61, 0x67 -> 字节0:0x66, 字节1:0x6C, 字节2:0x61, 字节3:0x67 -> 对应字符:'f','l','a','g'
I1: 0x7B, 0x6C, 0x6C, 0x69 -> 字符:'{','l','l','i'
I2: 0x74, 0x74, 0x6C, 0x5F -> 字符:'t','t','l','_'
I3: 0x45, 0x6E, 0x64, 0x69 -> 字符:'E','n','d','i'
I4: 0x61, 0x6E, 0x5F, 0x61 -> 字符:'a','n','_','a'
所以整个字符串是:flag{llittl_Endian_a
这看起来不像flag,但注意:程序就是这样验证的。
但是,我们可能犯了错误:数组array中的数据我们取错了?
看.rodata段:
.rodata:0000000000002010 array db 1Eh, 3Ah, 55h, 75h, 03h, 3Ah, 58h, 7Bh, 0Ch, 22h, 58h, 4Dh, 3Dh, 38h, 50h, 7Bh, 19h, 38h, 6Bh, 73h
我们划分的5个整数:
整数1: 75 55 3A 1E -> 0x75553A1E (正确)
整数2: 7B 58 3A 03 -> 0x7B583A03 (正确)
整数3: 4D 58 22 0C -> 0x4D58220C (正确)
整数4: 7B 50 38 3D -> 0x7B50383D (正确)
整数5: 73 6B 38 19 -> 0x736B3819 (正确)
异或计算也没有问题,所以这个flag就是"flag{llittl_Endian_a"?
但注意,字符串长度为19(最后没有0,因为整数5的最后一个字节是0x61,不是0),而程序只比较5个整数(20字节),所以输入时需要输入20个字节,包括最后的一个字符'a'。
然而,这个字符串看起来没有意义。我们再检查一下异或计算:
0x75553A1E ^ 0x12345678 = 0x67616C66 -> 正确
0x7B583A03 ^ 0x12345678 -> 7B583A03的二进制: 01111011 01011000 00111010 00000011
12345678: 00010010 00110100 01010110 01111000
逐位异或: 01101001 01101100 01101100 01111011 -> 0x696C6C7B -> 正确
那么,有没有可能是我们误解了数组元素的顺序?程序在取数组元素时,用的是:
movsxd rdx, edx
lea rcx, ds:0[rdx*4]
lea rdx, array
mov edx, [rcx+rdx]
这显然是以rdx为索引(0~4),取array[rdx](每个元素4字节)。
所以划分是正确的。
结论:程序验证的flag就是"flag{llittl_Endian_a"?
但是,这看起来不像合理的flag。我们可能漏掉了什么?注意,循环5次,每次4字节,共20字节。
另一种思路:也许异或的操作数0x12345678在程序中应该是小端存储?但是它是一个立即数,在指令中是12345678h,所以就是0x12345678。
再或者,程序在比较时,将输入的整数也做了小端转换?但是输入是从用户字符串读取的,scanf("%s"),所以输入的字符串在内存中按顺序排列,然后程序将其视为32位整数数组(小端)。
所以,如果我们要输入一个字符串使得程序验证通过,那么我们应该构造一个20字节的字符串,使得每4字节组成的小端整数等于array中对应整数异或0x12345678。
我们计算出的20个字节就是:
66,6C,61,67, 7B,6C,6C,69, 74,74,6C,5F, 45,6E,64,69, 61,6E,5F,61
对应的字符串:flag{llittl_Endian_a
但是,注意:字符串中的字符顺序:
第0字节:0x66 -> 'f'
第1字节:0x6C -> 'l'
第2字节:0x61 -> 'a'
第3字节:0x67 -> 'g'
第4字节:0x7B -> '{'
第5字节:0x6C -> 'l'
第6字节:0x6C -> 'l'
第7字节:0x69 -> 'i'
第8字节:0x74 -> 't'
第9字节:0x74 -> 't'
第10字节:0x6C -> 'l'
第11字节:0x5F -> '_'
第12字节:0x45 -> 'E'
第13字节:0x6E -> 'n'
第14字节:0x64 -> 'd'
第15字节:0x69 -> 'i'
第16字节:0x61 -> 'a'
第17字节:0x6E -> 'n'
第18字节:0x5F -> '_'
第19字节:0x61 -> 'a'
所以字符串是:flag{llittl_Endian_a
这看起来像是一个错误的flag,因为我们期望常见的flag格式,并且"llittl"可能是"little"的拼写错误?注意,我们计算的字符串中,第5-10字节是"llittl",这显然是重复了。
重新考虑:有没有可能数组中的数据不是每4字节一组?或者循环的次数不对?
代码中:
mov dword ptr [rbp-3Ch], 0 ; 计数器
loc_126E:
cmp dword ptr [rbp-3Ch], 4
jle short loc_121F ; 计数器<=4时循环,所以计数器=0,1,2,3,4 -> 5次
每次计数器增加1,输入指针增加4(add qword ptr [rbp-38h], 4)
所以是5次循环,共20字节。
那么我们计算的字符串应该是正确的,尽管看起来不合理。
但是,我们注意到:在数组的后面还有数据吗?数组在.rodata中只有20个字节(0000000000002010到0000000000002023),所以5个整数用完。
最后,我们或许可以尝试输入这个字符串看看程序输出?但因为这是一个离线分析,我们只能相信计算。
另一种可能性:整数5的计算有误,因为数组到73h结束,而我们取了73 6B 38 19作为第五个整数。
但是,数组的最后一个字节是73h(地址2023),而第五个整数就是从2020开始的4字节:19 38 6B 73 -> 0x736B3819。
综上所述,flag为:flag{llittl_Endian_a
但是,注意:这个字符串中包含了非打印字符?不,0x7B是'{',其他的都在可打印ASCII范围内。
我们将其写出来:flag{llittl_Endian_a
这可能是一个故意设计的字符串,或者是另有含义。
因此,答案就是:flag{llittl_Endian_a
但是,我们再看一下,字符串中有一个大写的'E',这不太常见。或许我们应该将第四组整数的小端字符串反转?不,程序是小端比较,我们分解的方式是正确的。
或许程序在比较时,对输入的字符串进行了转换?但代码中没有看到。
所以,最终的flag:flag{llittl_Endian_a
注意:用户输入时,需要输入20个字符,包括最后的'a'。
但通常flag会有'}'结束,这里却没有。所以可能这个题目设计如此。
我们输出flag:flag{llittl_Endian_a
不过,为了严谨,我们也可以尝试将每4字节反转(即不使用小端解释)?但程序代码明确使用了小端(因为直接取4字节内存作为整数)。
因此,我们坚持认为flag是:flag{llittl_Endian_a
但是,当我们拼接时,发现从第4字节开始的下一部分"{lli"之后是"ttl_",然后"Endi"和"an_a",连起来是:{llittl_Endian_a -> 或许是{ little_Endian_a ... },但这里拼写为"llittl"。
可能题目本意是想表达:flag{little_Endian_flag},但现在的结果不对。
重新计算array数组的异或,可能 immediate value 0x12345678 应该用小端解释?也就是说,立即数0x12345678在内存中是78 56 34 12,所以异或时应该用0x78563412?
我们试试:
整数1: 0x75553A1E ^ 0x78563412 =
1E^12 = 0C
3A^34 = 0E
55^56 = 03
75^78 = 0D
0x0D030E0C -> 小端字符串:0C 0E 03 0D -> 非打印字符 -> 不合理。
所以不是。
另一种可能:立即数0x12345678作为小端整数,其值还是0x12345678,所以异或时还是用0x12345678。
因此,我们只能接受flag{llittl_Endian_a
最后,我们输出flag:flag{llittl_Endian_a
但是,请注意,第五个整数0x615F6E61的最后一位是0x61('a'),而字符串结束符是0,所以程序如果使用字符串函数可能会提前结束,但这里并没有,因为程序只比较20字节。
因此,flag就是 flag{llittl_Endian_a
综上所述,我们得出结论:程序的flag为"flag{llittl_Endian_a"。
然而,我们再看数组内容:array的后4个字节是19,38,6B,73,异或后的最后4个字节是61,6E,5F,61,对应的字符串"an_a"。这可能表示"an_a"是"and a"的意思,但拼写上是"an_a"。
所以,最后的flag:flag{llittl_Endian_a
我们将其写为:flag{llittl_Endian_a
为了确保,我们也可以动态调试,但这里无法进行。
因此,答案是:flag{llittl_Endian_a
注意:在提交flag时,要 exactly 这个字符串。
不过,我们再看一下数组:0000000000002010 array db 1Eh, 3Ah, 55h, 75h, 03h, 3Ah, 58h, 7Bh, 0Ch, 22h, 58h, 4Dh, 3Dh, 38h, 50h, 7Bh, 19h, 38h, 6Bh, 73h
有没有可能数组的元素不是顺序的?代码中 array[0] 对应 db 1Eh,3Ah,55h,75h 这4字节,是连续的。
所以,我们确定flag。
</think>### 汇编代码分析总结
#### 1. 程序功能分析
该程序是一个简单的flag验证程序,主要逻辑在`main`函数中:
1. 打印提示信息:"please input your flag"
2. 使用`scanf("%s")`读取用户输入到栈缓冲区`[rbp-30h]`
3. 将输入视为**5个32位整数数组**(小端序),与预定义数组`array`进行校验:
```assembly
loc_121F:
mov rax, [rbp-38h] ; 当前输入指针
mov eax, [rax] ; 加载4字节输入值
movsxd rdx, edx
lea rcx, ds:0[rdx*4] ; 计算数组索引
lea rdx, array
mov edx, [rcx+rdx] ; 加载array[i]
xor edx, 12345678h ; 关键异或操作
cmp eax, edx ; 比较校验值
jz short loc_1265 ; 相等则继续
; 否则打印"wrong!"并退出
```
4. 循环5次(计数器0~4),每次校验4字节
5. 全部校验通过则打印"you are right"
#### 2. 关键数据结构
- **预定义数组(.rodata段)**:
```assembly
.rodata:0000000000002010 array db 1Eh, 3Ah, 55h, 75h, 03h, 3Ah, 58h, 7Bh, 0Ch, 22h, 58h, 4Dh, 3Dh, 38h, 50h, 7Bh, 19h, 38h, 6Bh, 73h
```
按32位小端整数解析为:
```
[0x75553A1E, 0x7B583A03, 0x4D58220C, 0x7B50383D, 0x736B3819]
```
#### 3. 校验算法
通过异或运算还原正确flag:
```math
\text{flag}_i = \text{array}[i] \oplus \text{0x12345678}
```
其中:
- $i$ 为索引(0~4)
- $\oplus$ 表示按位异或
- 结果需按**小端序**转换为ASCII字符
#### 4. Flag计算过程
| 步骤 | 数组值 (十六进制) | 异或运算 (十六进制) | 小端字节 | ASCII字符 |
|------|------------------|--------------------|----------|-----------|
| 1 | 0x75553A1E | 0x75553A1E ⊕ 0x12345678 = 0x67616C66 | 66 6C 61 67 | `flag` |
| 2 | 0x7B583A03 | 0x7B583A03 ⊕ 0x12345678 = 0x696C6C7B | 7B 6C 6C 69 | `{lli` |
| 3 | 0x4D58220C | 0x4D58220C ⊕ 0x12345678 = 0x5F6C7474 | 74 74 6C 5F | `ttl_` |
| 4 | 0x7B50383D | 0x7B50383D ⊕ 0x12345678 = 0x69646E45 | 45 6E 64 69 | `Endi` |
| 5 | 0x736B3819 | 0x736B3819 ⊕ 0x12345678 = 0x615F6E61 | 61 6E 5F 61 | `an_a` |
**完整Flag**:`flag{llittl_Endian_a`
(20字节,无终止符)
### 调用关系
```mermaid
graph TD
A[main] --> B[printf '请输入flag']
A --> C[scanf 读取输入]
A --> D{循环校验}
D --> E[加载输入值]
D --> F[加载array元素]
D --> G[XOR 0x12345678]
D --> H[比较]
H -->|匹配| I[继续循环]
H -->|不匹配| J[puts 'wrong!'并退出]
I --> K[索引+1]
K -->|循环5次| D
D -->|完成| L[puts 'you are right']
```
### 其他段功能说明
1. **.init_array**:存储初始化函数(`frame_dummy`)
2. **.fini_array**:存储终止函数(`__do_global_dtors_aux`)
3. **.got**:全局偏移表,存储外部函数指针
- 如`__libc_start_main`, `puts`, `exit`等
4. **.eh_frame**:异常处理框架信息
5. **LOAD段**:包含动态链接信息(如ELF头、程序头表)