Login

这道题里面给了两个文件,一个作为了客户端,一个作为服务器,两个程序之间相互传输数据,对登录的token、password以及verify这三个数进行了验证。

验证的主逻辑是在check程序之中,这里有三中加密(RSA、Hill、AES),这次的AES进行了魔改,解密的脚本不得不自己来码代码!!

两个程序的交互

提供了两个文件,一个文佳时客户端界面,一个时服务器界面,要实现两个页面的交互

打开的是两个程序,一个程序作为的是客户端(login),一个作为的是服务器(check)

在这两个程序之中找到start函数,然后打开第一个参数,就是main函数

image-20220418182800620

login程序:

  • 和服务器进行一系列的交互
  • 一个while循环向服务器发送和接受消息
  • 其中的if语句会根据接受到的参数,来做出特定的反应

连接服务器:

image-20220418185651992

客户端和服务器间的交互:

image-20220418190656569

if语句发送数据:

image-20220418184030804image-20220418184014037

客户端:

连接客户端:

image-20220418185943841

进入main函数之中,和客户端进行交互,验证三个数据

image-20220418232408361

rsa解密

大素数:

1
13123058934861171416713230498081453101147538789122070079961388806126697916963123413431108069961369055630747412550900239402710827847917960870358653962948282381351741121884528399369764530446509936240262290248305226552117100584726616255292963971141510518678552679033220315246377746270515853987903184512948801397452104554589803725619076066339968999308910127885089547678968793196148780382182445270838659078189316664538631875879022325427220682805580410213245364855569367702919157881367085677283124732874621569379901272662162025780608669577546548333274766058755786449491277002349918598971841605936268030140638579388226573929

分解的质数:

1
2
3
p = 98197216341757567488149177586991336976901080454854408243068885480633972200382596026756300968618883148721598031574296054706280190113587145906781375704611841087782526897314537785060868780928063942914187241017272444601926795083433477673935377466676026146695321415853502288291409333200661670651818749836420808033
q = 133639826298015917901017908376475546339925646165363264658181838203059432536492968144231040597990919971381628901127402671873954769629458944972912180415794436700950304720548263026421362847590283353425105178540468631051824814390421486132775876582962969734956410033443729557703719598998956317920674659744121941513
e = 0x10001

密文:

1
c = 0x2e7469206873696c6f70206577206e6f697461737265766e6f63207962202c646e696d2065687420686369726e6520657720676e6964616572207942

解密脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
import gmpy2
def Decrypt(c,e,p,q):
L = (p-1)*(q-1)
d = gmpy2.invert(e,L)
n = p * q
m = gmpy2.powmod(c, d, n)
flag = str(m)
print(flag)
p = 98197216341757567488149177586991336976901080454854408243068885480633972200382596026756300968618883148721598031574296054706280190113587145906781375704611841087782526897314537785060868780928063942914187241017272444601926795083433477673935377466676026146695321415853502288291409333200661670651818749836420808033
q = 133639826298015917901017908376475546339925646165363264658181838203059432536492968144231040597990919971381628901127402671873954769629458944972912180415794436700950304720548263026421362847590283353425105178540468631051824814390421486132775876582962969734956410033443729557703719598998956317920674659744121941513
e = 0x10001
c = 0x2e7469206873696c6f70206577206e6f697461737265766e6f63207962202c646e696d2065687420686369726e6520657720676e6964616572207942
Decrypt(c,e,p,q)

明文:

1
token = 11963777321199993924175387978397443935563034091716786597947508874393819454915798980986262132792605021295930274531653741552766395859285325677395421549163602968276475448835066393456449574469736327622969755801884982386140722904578598391534204834007447860153096480268812700725451958035204357033892179559153729604237187552716580637492579876006993181920209114166153317182827927606249871955662032809256743464460825303610341043145126848787575238499023185150429072724679210155061579052743238859739734301162335989939278904459012917375108407803445722785027315562371588439877746983153339473213449448259686486917983129418859935686

hill解密

密钥矩阵:

1
2
3
4
5
6
7
8
9
0xA34C0F7A2E25DB71,0x7AA91B6E29AA226A,0x56AA0EF0802F278A,0x9AF6F2A9005859F7,0xC9481C4E
形成6*6的矩阵 (GF(257))
0x71,0xdb,0x25,0x2e,0x7a,0x0f
0x4c,0xa3,0x6a,0x22,0xaa,0x29
0x6e,0x1b,0xa9,0x7a,0x8a,0x27
0x2f,0x80,0xf0,0x0e,0xaa,0x56
0xf7,0x59,0x58,0x00,0xa9,0xf2
0xf6,0x9a,0x4e,0x1c,0x48,0xc9
[[0x71,0xdb,0x25,0x2e,0x7a,0x0f],[0x4c,0xa3,0x6a,0x22,0xaa,0x29],[0x6e,0x1b,0xa9,0x7a,0x8a,0x27],[0x2f,0x80,0xf0,0x0e,0xaa,0x56],[0xf7,0x59,0x58,0x00,0xa9,0xf2],[0xf6,0x9a,0x4e,0x1c,0x48,0xc9]]

密文随机数(GF(255)):

1
1804289383,846930886,1681692777,1714636915,1957747793,424238335,719885386,1649760492,596516649,1189641421,1025202362,1350490027,783368690,1102520059,2044897763,1967513926,1365180540,1540383426,304089172,1303455736,35005211,521595368,294702567,1726956429,336465782,861021530,278722862,233665123,2145174067,468703135,1101513929,1801979802,1315634022,635723058,1369133069,1125898167,1059961393,2089018456,628175011,1656478042,1131176229,1653377373,859484421,1914544919,608413784,756898537,1734575198,1973594324,149798315,2038664370,1129566413,184803526,412776091,1424268980,1911759956,749241873,137806862,42999170,982906996,135497281,511702305,2084420925,1937477084,1827336327,572660336,1159126505,805750846,1632621729,1100661313,1433925857,1141616124,84353895,939819582,2001100545,1998898814,1548233367,610515434,1585990364,1374344043,760313750,1477171087,356426808,945117276,1889947178,1780695788,709393584,491705403,1918502651,752392754,1474612399,2053999932,1264095060,1411549676,1843993368,943947739,1984210012,855636226,1749698586,1469348094,1956297539

密文矩阵:

1
[[0xa3,0x97,0xa2,0x55,0x53,0xbe],[0xf1,0xfc,0xf9,0x79,0x6b,0x52],[0x14,0x13,0xe9,0xe2,0x2d,0x51],[0x8e,0x1f,0x56,0x08,0x57,0x27],[0xa7,0x05,0xd4,0xd0,0x52,0x82],[0x77,0x75,0x1b,0x99,0x4a,0xed]]

使用sage解矩阵的乘法运算

问题:这个函数的作用为什么是将输入的password(明文)转换成array形式

image-20220419214617366

计算得到数据:

1
2
3
4
5
6
7
[ 81  50 210   2 195  45]
[149 185 249 120 213 20]
[227 41 66 32 81 59]
[ 21 98 52 130 180 192]
[ 46 154 253 232 186 213]
[236 7 72 106 84 136]
所以password是:5132d202c32d95b9f978d514e3294220513b15623482b4c02e9afde8bad5ec07486a5488

将上面的token和login的数据输入之后登录成功:

image-20220419225219658

运行调试两个程序

如果需要动调:

ida之中动调的对象是服务器端口:

在Linux之中 使用./linux_server64 -p 1234 监听1234端口

在ida之中设置的端口号也应该是1234

image-20220419225918050

在Linux之中运行一下这两个程序

先将服务端运行起来 ./check

然后将客户端运行起来 ./login 127.0.0.1 // 因为服务端是在本地运行的,所以ip address 就是127.0.0.1

客户端需要输入ip address

image-20220419224934834

image-20220419225000482

AES解密

常规AES加密解密

魔改的部分:

  • S盒子和逆S盒交换着使用了
  • 密钥扩展中异或的部分魔改了
  • 在进入加密器之前进行了和IV向量的异或运算

这里面数据提取和处理的方法也要注意

S盒

S盒的生成:S盒的大小规格是16*16 = 256的

客户端接受到的数据是:

1
52096ad53036a538bf40a39e81f3d7fb7ce339829b2fff87348e4344c4dee9cb547b9432a6c2233dee4c950b42fac34e082ea16628d924b2765ba2496d8bd12572f8f66486689816d4a45ccc5d65b6926c704850fdedb9da5e154657a78d9d8490d8ab008cbcd30af7e45805b8b34506d02c1e8fca3f0f02c1afbd0301138a6b3a9111414f67dcea97f2cfcef0b4e67396ac7422e7ad3585e2f937e81c75df6e47f11a711d29c5896fb7620eaa18be1bfc563e4bc6d279209adbc0fe78cd5af41fdda8338807c731b11210592780ec5f60517fa919b54a0d2de57a9f93c99cefa0e03b4dae2af5b0c8ebbb3c83539961172b047eba77d626e169146355210c7d

利用接受到的数据生成S盒

1
0x52,0x09,0x6a,0xd5,0x30,0x36,0xa5,0x38,0xbf,0x40,0xa3,0x9e,0x81,0xf3,0xd7,0xfb,0x7c,0xe3,0x39,0x82,0x9b,0x2f,0xff,0x87,0x34,0x8e,0x43,0x44,0xc4,0xde,0xe9,0xcb,0x54,0x7b,0x94,0x32,0xa6,0xc2,0x23,0x3d,0xee,0x4c,0x95,0x0b,0x42,0xfa,0xc3,0x4e,0x08,0x2e,0xa1,0x66,0x28,0xd9,0x24,0xb2,0x76,0x5b,0xa2,0x49,0x6d,0x8b,0xd1,0x25,0x72,0xf8,0xf6,0x64,0x86,0x68,0x98,0x16,0xd4,0xa4,0x5c,0xcc,0x5d,0x65,0xb6,0x92,0x6c,0x70,0x48,0x50,0xfd,0xed,0xb9,0xda,0x5e,0x15,0x46,0x57,0xa7,0x8d,0x9d,0x84,0x90,0xd8,0xab,0x00,0x8c,0xbc,0xd3,0x0a,0xf7,0xe4,0x58,0x05,0xb8,0xb3,0x45,0x06,0xd0,0x2c,0x1e,0x8f,0xca,0x3f,0x0f,0x02,0xc1,0xaf,0xbd,0x03,0x01,0x13,0x8a,0x6b,0x3a,0x91,0x11,0x41,0x4f,0x67,0xdc,0xea,0x97,0xf2,0xcf,0xce,0xf0,0xb4,0xe6,0x73,0x96,0xac,0x74,0x22,0xe7,0xad,0x35,0x85,0xe2,0xf9,0x37,0xe8,0x1c,0x75,0xdf,0x6e,0x47,0xf1,0x1a,0x71,0x1d,0x29,0xc5,0x89,0x6f,0xb7,0x62,0x0e,0xaa,0x18,0xbe,0x1b,0xfc,0x56,0x3e,0x4b,0xc6,0xd2,0x79,0x20,0x9a,0xdb,0xc0,0xfe,0x78,0xcd,0x5a,0xf4,0x1f,0xdd,0xa8,0x33,0x88,0x07,0xc7,0x31,0xb1,0x12,0x10,0x59,0x27,0x80,0xec,0x5f,0x60,0x51,0x7f,0xa9,0x19,0xb5,0x4a,0x0d,0x2d,0xe5,0x7a,0x9f,0x93,0xc9,0x9c,0xef,0xa0,0xe0,0x3b,0x4d,0xae,0x2a,0xf5,0xb0,0xc8,0xeb,0xbb,0x3c,0x83,0x53,0x99,0x61,0x17,0x2b,0x04,0x7e,0xba,0x77,0xd6,0x26,0xe1,0x69,0x14,0x63,0x55,0x21,0x0c,0x7d

pass_token的获取

image-20220420162301465

token的数组数据:(按照char的类型来取值)

1
token = "11963777321199993924175387978397443935563034091716786597947508874393819454915798980986262132792605021295930274531653741552766395859285325677395421549163602968276475448835066393456449574469736327622969755801884982386140722904578598391534204834007447860153096480268812700725451958035204357033892179559153729604237187552716580637492579876006993181920209114166153317182827927606249871955662032809256743464460825303610341043145126848787575238499023185150429072724679210155061579052743238859739734301162335989939278904459012917375108407803445722785027315562371588439877746983153339473213449448259686486917983129418859935686"

pass的数组数据:

1
0x51,0x32,0xd2,0x02,0xc3,0x2d,0x95,0xb9,0xf9,0x78,0xd5,0x14,0xe3,0x29,0x42,0x20,0x51,0x3b,0x15,0x62,0x34,0x82,0xb4,0xc0,0x2e,0x9a,0xfd,0xe8,0xba,0xd5,0xec,0x07,0x48,0x6a,0x54,0x88

随机数:

1
1804289383,846930886,1681692777,1714636915,1957747793,424238335,719885386,1649760492,596516649,1189641421,1025202362,1350490027,783368690,1102520059,2044897763,1967513926,1365180540,1540383426,304089172,1303455736,35005211,521595368,294702567,1726956429,336465782,861021530,278722862,233665123,2145174067,468703135,1101513929,1801979802,1315634022,635723058,1369133069,1125898167,1059961393,2089018456,628175011,1656478042,1131176229,1653377373,859484421,1914544919,608413784,756898537,1734575198,1973594324,149798315,2038664370,1129566413,184803526,412776091,1424268980,1911759956,749241873,137806862,42999170,982906996,135497281,511702305,2084420925,1937477084,1827336327,572660336,1159126505,805750846,1632621729,1100661313,1433925857,1141616124,84353895,939819582,2001100545,1998898814,1548233367,610515434,1585990364,1374344043,760313750,1477171087,356426808,945117276,1889947178,1780695788,709393584,491705403,1918502651,752392754,1474612399,2053999932,1264095060,1411549676,1843993368,943947739,1984210012,855636226,1749698586,1469348094,1956297539

生成pass_token:(IV和密钥)这里的随机数使用的是第36个随机数之后的数,因为在程序的前面生成过一次36个随机数。

1
2
3
4
5
6
7
8
9
10
11
token = "11963777321199993924175387978397443935563034091716786597947508874393819454915798980986262132792605021295930274531653741552766395859285325677395421549163602968276475448835066393456449574469736327622969755801884982386140722904578598391534204834007447860153096480268812700725451958035204357033892179559153729604237187552716580637492579876006993181920209114166153317182827927606249871955662032809256743464460825303610341043145126848787575238499023185150429072724679210155061579052743238859739734301162335989939278904459012917375108407803445722785027315562371588439877746983153339473213449448259686486917983129418859935686"
password = [0x51,0x32,0xd2,0x02,0xc3,0x2d,0x95,0xb9,0xf9,0x78,0xd5,0x14,0xe3,0x29,0x42,0x20,0x51,0x3b,0x15,0x62,0x34,0x82,0xb4,0xc0,0x2e,0x9a,0xfd,0xe8,0xba,0xd5,0xec,0x07,0x48,0x6a,0x54,0x88]
random = [1804289383,846930886,1681692777,1714636915,1957747793,424238335,719885386,1649760492,596516649,1189641421,1025202362,1350490027,783368690,1102520059,2044897763,1967513926,1365180540,1540383426,304089172,1303455736,35005211,521595368,294702567,1726956429,336465782,861021530,278722862,233665123,2145174067,468703135,1101513929,1801979802,1315634022,635723058,1369133069,1125898167,1059961393,2089018456,628175011,1656478042,1131176229,1653377373,859484421,1914544919,608413784,756898537,1734575198,1973594324,149798315,2038664370,1129566413,184803526,412776091,1424268980,1911759956,749241873,137806862,42999170,982906996,135497281,511702305,2084420925,1937477084,1827336327,572660336,1159126505,805750846,1632621729,1100661313,1433925857,1141616124,84353895,939819582,2001100545,1998898814,1548233367,610515434,1585990364,1374344043,760313750,1477171087,356426808,945117276,1889947178,1780695788,709393584,491705403,1918502651,752392754,1474612399,2053999932,1264095060,1411549676,1843993368,943947739,1984210012,855636226,1749698586,1469348094,1956297539]
token_pass=[]
for i in range(48):
if i&1 != 0:
token_pass.append(ord(token[random[i+36]%len(token)]))
else:
token_pass.append(password[random[i+36]%len(password)])
print(token_pass)
token_pass = [50, 48, 7, 54, 106, 55, 120, 49, 72, 57, 66, 57, 20, 49, 213, 50, 98, 54, 249, 56, 66, 48, 195, 49, 106, 53, 72, 56, 52, 53, 84, 52, 41, 52, 81, 54, 21, 57, 210, 56, 210, 57, 32, 49, 185, 50, 46, 48]

密钥扩展和逆S盒

这里和常规的AES的密钥扩展是进行了魔改的(对比常规的AES加密的代码就能知道,密钥扩展这部分的代码需要自己写)

生成SBox的逆矩阵:

image-20220420163223716

image-20220421131943315

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
revSBox = [
0x63,0x7c,0x77,0x7b,0xf2,0x6b,0x6f,0xc5,0x30,0x01,0x67,0x2b,0xfe,0xd7,0xab,0x76,
0xca,0x82,0xc9,0x7d,0xfa,0x59,0x47,0xf0,0xad,0xd4,0xa2,0xaf,0x9c,0xa4,0x72,0xc0,
0xb7,0xfd,0x93,0x26,0x36,0x3f,0xf7,0xcc,0x34,0xa5,0xe5,0xf1,0x71,0xd8,0x31,0x15,
0x04,0xc7,0x23,0xc3,0x18,0x96,0x05,0x9a,0x07,0x12,0x80,0xe2,0xeb,0x27,0xb2,0x75,
0x09,0x83,0x2c,0x1a,0x1b,0x6e,0x5a,0xa0,0x52,0x3b,0xd6,0xb3,0x29,0xe3,0x2f,0x84,
0x53,0xd1,0x00,0xed,0x20,0xfc,0xb1,0x5b,0x6a,0xcb,0xbe,0x39,0x4a,0x4c,0x58,0xcf,
0xd0,0xef,0xaa,0xfb,0x43,0x4d,0x33,0x85,0x45,0xf9,0x02,0x7f,0x50,0x3c,0x9f,0xa8,
0x51,0xa3,0x40,0x8f,0x92,0x9d,0x38,0xf5,0xbc,0xb6,0xda,0x21,0x10,0xff,0xf3,0xd2,
0xcd,0x0c,0x13,0xec,0x5f,0x97,0x44,0x17,0xc4,0xa7,0x7e,0x3d,0x64,0x5d,0x19,0x73,
0x60,0x81,0x4f,0xdc,0x22,0x2a,0x90,0x88,0x46,0xee,0xb8,0x14,0xde,0x5e,0x0b,0xdb,
0xe0,0x32,0x3a,0x0a,0x49,0x06,0x24,0x5c,0xc2,0xd3,0xac,0x62,0x91,0x95,0xe4,0x79,
0xe7,0xc8,0x37,0x6d,0x8d,0xd5,0x4e,0xa9,0x6c,0x56,0xf4,0xea,0x65,0x7a,0xae,0x08,
0xba,0x78,0x25,0x2e,0x1c,0xa6,0xb4,0xc6,0xe8,0xdd,0x74,0x1f,0x4b,0xbd,0x8b,0x8a,
0x70,0x3e,0xb5,0x66,0x48,0x03,0xf6,0x0e,0x61,0x35,0x57,0xb9,0x86,0xc1,0x1d,0x9e,
0xe1,0xf8,0x98,0x11,0x69,0xd9,0x8e,0x94,0x9b,0x1e,0x87,0xe9,0xce,0x55,0x28,0xdf,
0x8c,0xa1,0x89,0x0d,0xbf,0xe6,0x42,0x68,0x41,0x99,0x2d,0x0f,0xb0,0x54,0xbb,0x16,
]
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
// 进行密钥扩展
void expandKeyNums()
{
// 进行密钥扩展
uint8_t v9 = 0;
uint8_t v10 = 0;
uint8_t v11 = 0;
uint8_t v12 = 0;
uint8_t i =0;
uint8_t j =0;
// 初始化前16个字节 4列中的元素
for(i = 0 ;i<4;i++)
{
roundKey[i*4] = pass_token[i*4];
roundKey[i*4+1] = pass_token[i*4+1];
roundKey[i*4+2] = pass_token[i*4+2];
roundKey[i*4+3] = pass_token[i*4+3];
}
for(i=4;i<44;i++)
{
v9 = roundKey[4*(i-1)];
v10 = roundKey[4*(i-1)+1];
v11 = roundKey[4*(i-1)+2];
v12 = roundKey[4*(i-1)+3];
if ((i&3) == 0 )
{
v10 = revSBox[v11];
v11 = revSBox[v12];
v12 = revSBox[roundKey[4*(i-1)]];
v9 = revSBox[roundKey[4*(i-1)+1]] ^ para[i>>2];
}
roundKey[i*4] = v9^roundKey[(i-4)*4];
roundKey[i*4+1] = v10^roundKey[(i-4)*4+1];
roundKey[i*4+2] = v11^roundKey[(i-4)*4+2];
roundKey[i*4+3] = v12^roundKey[(i-4)*4+3];
}
}

CBC模式的初始化向量的IV

作为IV的pass_token的后16*2个字节,每次使用16个字节

image-20220421132904388

image-20220420224347131

密文:

1
c ={0xfe,0xf9,0xe7,0x3e,0xf6,0xa1,0x23,0xcc,0x57,0x61,0xc1,0x15,0x77,0xfb,0x9c,0xbb,0xca,0x2f,0xb1,0xe8,0x4f,0xd9,0x07,0xd8,0x0c,0x6b,0xea,0xcf,0xe8,0x42,0xa2,0xfa}
1
2
3
4
5
6
7
8
// 加密过程第一步的异或运算(但是里面的数据还需要思考一下) 传入的参数是数据加密的轮数
void XorIV(uint8_t round)
{
for(int i=0;i<=15;i++)
{
verify[i]^=pass_token[16*round+16+i];
}
}

AES加密的主逻辑

image-20220421133028414

字节代换

这里用的S盒是revDate(SBox)

image-20220420175507903

逆字节代换(要用revSBox)

1
2
3
4
5
6
7
8
9
// 逆字节代换()
void reveSubBytes()
{
for(int i=0; i<16; i++)
{
verify[i] = revSBox[verify[i]];
}

}

行移位

行移位操作:

image-20220420180004983

行移位的逆运算:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 行移位的逆运算 第一行不移动 第二行循环右移1位
void reveShiftRows()
{
int round = 0;
uint8_t tem = 0;//临时存放值
int j =0;
for (int i=0;i<4;i++)
{
round = i;
while(round)
{
tem = verify[i*4+3];
for(j=3;j>0;j--)
{
verify[i*4+j] = verify[i*4+j-1];
}
verify[i*4+j] = tem;
round--;
}
}
}

列混合

列混合:

image-20220420185629111

用到的矩阵(4*4)

1
2
3
4
0x02, 0x03, 0x01, 0x01, 
0x01, 0x02, 0x03, 0x01,
0x01, 0x01, 0x02, 0x03,
0x03, 0x01, 0x01, 0x02,

GF之中的运算:

image-20220420190421308

逆列混合使用到的矩阵:

1
2
3
4
   0xe, 0xb, 0xd, 0x9,
0x9, 0xe, 0xb, 0xd,
0xd, 0x9, 0xe, 0xb,
0xb, 0xd, 0x9, 0xe

逆列混合:

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
// 列混合
// 使用到的矩阵
static const uint8_t deColCinfusion[16] =
{
0xe, 0xb, 0xd, 0x9,
0x9, 0xe, 0xb, 0xd,
0xd, 0x9, 0xe, 0xb,
0xb, 0xd, 0x9, 0xe
};

// GF之中的运算
static uint8_t GFMul2(uint8_t s)
{
uint8_t result = s*2;
int tem = (s*2)&0x00000100;
if(tem != 0)
{
result = result&0xff;
result^= 0x1b;
}
return result;
}

static uint8_t GFMul3(uint8_t s)
{
return GFMul2(s)^s;
}

static uint8_t GFMul4(uint8_t s)
{
return GFMul2(GFMul2(s));
}

static uint8_t GFMul8(uint8_t s)
{
return GFMul2(GFMul4(s));
}

static uint8_t GFMul9(uint8_t s)
{
return GFMul8(s)^s;
}

static uint8_t GFMul11(uint8_t s)
{
return GFMul9(s)^GFMul2(s);
}

static uint8_t GFMul12(uint8_t s)
{
return GFMul8(s)^GFMul4(s);
}

static uint8_t GFMul13(uint8_t s)
{
return GFMul12(s)^s;
}

static uint8_t GFMul14(uint8_t s)
{
return GFMul12(s)^GFMul2(s);
}

static uint8_t GFMul(uint8_t n,uint8_t s)
{
uint8_t result = 0;
if (n==1)
result = s;
else if (n==2) // 2
result = GFMul2(s);
else if (n==3) // 3
result = GFMul3(s);
else if (n==0x9) // 9
result = GFMul9(s);
else if (n==0xb) // 11
result = GFMul11(s);
else if (n==0xd) // 13
result = GFMul13(s);
else if (n==0xe) // 14
result = GFMul14(s);
return result;
}

// 逆列混合

static void deColCinfusions()
{
uint8_t temVerify[16];
uint8_t i =0;
uint8_t j =0;
for(i=0;i<16;i++)
{
temVerify[i] = verify[i];
}

for (i =0;i<4;i++)
{
for(j=0;j<4;j++)
{
verify[i*4+j] = GFMul(deColCinfusion[i*4],temVerify[j])^GFMul(deColCinfusion[i*4+1],temVerify[4+j])^GFMul(deColCinfusion[i*4+2],temVerify[2*4+j])^GFMul(deColCinfusion[i*4+3],temVerify[3*4+j]);
}
}
}

轮密钥加

轮密钥加:

image-20220420221626691

在10轮加密之前会使用一个拓展密钥(进行一次轮密钥加)

10轮加密之中每一轮会用一个拓展密钥

10轮加密之后会使用一个拓展密钥

image-20220420222043252

逆轮密钥加:

1
2
3
4
5
6
7
8
9
10
11
12
// 轮密钥加(传入的参数是每一轮使用的密钥的第一个数的索引)
static void addRoundKey(uint8_t theIndex)
{
uint8_t i,j = 0;
for(i=0;i<4;i++)
{
for(j=0;j<4;j++)
{
verify[4*i+j]^=roundKey[theIndex+4*j+i];
}
}
}

AES解密脚本

AES解密脚本:

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
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
uint8_t revSBox[] = {0x63,0x7c,0x77,0x7b,0xf2,0x6b,0x6f,0xc5,0x30,0x01,0x67,0x2b,0xfe,0xd7,0xab,0x76,0xca,0x82,0xc9,0x7d,0xfa,0x59,0x47,0xf0,0xad,0xd4,0xa2,0xaf,0x9c,0xa4,0x72,0xc0,0xb7,0xfd,0x93,0x26,0x36,0x3f,0xf7,0xcc,0x34,0xa5,0xe5,0xf1,0x71,0xd8,0x31,0x15,0x04,0xc7,0x23,0xc3,0x18,0x96,0x05,0x9a,0x07,0x12,0x80,0xe2,0xeb,0x27,0xb2,0x75,0x09,0x83,0x2c,0x1a,0x1b,0x6e,0x5a,0xa0,0x52,0x3b,0xd6,0xb3,0x29,0xe3,0x2f,0x84,0x53,0xd1,0x00,0xed,0x20,0xfc,0xb1,0x5b,0x6a,0xcb,0xbe,0x39,0x4a,0x4c,0x58,0xcf,0xd0,0xef,0xaa,0xfb,0x43,0x4d,0x33,0x85,0x45,0xf9,0x02,0x7f,0x50,0x3c,0x9f,0xa8,0x51,0xa3,0x40,0x8f,0x92,0x9d,0x38,0xf5,0xbc,0xb6,0xda,0x21,0x10,0xff,0xf3,0xd2,0xcd,0x0c,0x13,0xec,0x5f,0x97,0x44,0x17,0xc4,0xa7,0x7e,0x3d,0x64,0x5d,0x19,0x73,0x60,0x81,0x4f,0xdc,0x22,0x2a,0x90,0x88,0x46,0xee,0xb8,0x14,0xde,0x5e,0x0b,0xdb,0xe0,0x32,0x3a,0x0a,0x49,0x06,0x24,0x5c,0xc2,0xd3,0xac,0x62,0x91,0x95,0xe4,0x79,0xe7,0xc8,0x37,0x6d,0x8d,0xd5,0x4e,0xa9,0x6c,0x56,0xf4,0xea,0x65,0x7a,0xae,0x08,0xba,0x78,0x25,0x2e,0x1c,0xa6,0xb4,0xc6,0xe8,0xdd,0x74,0x1f,0x4b,0xbd,0x8b,0x8a,0x70,0x3e,0xb5,0x66,0x48,0x03,0xf6,0x0e,0x61,0x35,0x57,0xb9,0x86,0xc1,0x1d,0x9e,0xe1,0xf8,0x98,0x11,0x69,0xd9,0x8e,0x94,0x9b,0x1e,0x87,0xe9,0xce,0x55,0x28,0xdf,0x8c,0xa1,0x89,0x0d,0xbf,0xe6,0x42,0x68,0x41,0x99,0x2d,0x0f,0xb0,0x54,0xbb,0x16};
uint8_t para[] = { 0x8D, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1B, 0x36};
uint8_t pass_token[] = {50, 48, 7, 54, 106, 55, 120, 49, 72, 57, 66, 57, 20, 49, 213, 50, 98, 54, 249, 56, 66, 48, 195, 49, 106, 53, 72, 56, 52, 53, 84, 52, 41, 52, 81, 54, 21, 57, 210, 56, 210, 57, 32, 49, 185, 50, 46, 48}; //前16个字节用来生成44*4的轮密钥 后16*2字节每16个字节用来进行AES的IV异或运算
uint8_t roundKey[4*44];// 生成的轮密钥
uint8_t verify[16];
// 待加密的数据
uint8_t c[] ={0xfe,0xf9,0xe7,0x3e,0xf6,0xa1,0x23,0xcc,0x57,0x61,0xc1,0x15,0x77,0xfb,0x9c,0xbb,0xca,0x2f,0xb1,0xe8,0x4f,0xd9,0x07,0xd8,0x0c,0x6b,0xea,0xcf,0xe8,0x42,0xa2,0xfa};

// 进行密钥扩展
void expandKeyNums()
{
// 进行密钥扩展
uint8_t v9 = 0;
uint8_t v10 = 0;
uint8_t v11 = 0;
uint8_t v12 = 0;
uint8_t i =0;
uint8_t j =0;
// 初始化前16个字节 4列中的元素
for(i = 0 ;i<4;i++)
{
roundKey[i*4] = pass_token[i*4];
roundKey[i*4+1] = pass_token[i*4+1];
roundKey[i*4+2] = pass_token[i*4+2];
roundKey[i*4+3] = pass_token[i*4+3];
}
for(i=4;i<44;i++)
{
v9 = roundKey[4*(i-1)];
v10 = roundKey[4*(i-1)+1];
v11 = roundKey[4*(i-1)+2];
v12 = roundKey[4*(i-1)+3];
if ((i&3) == 0 )
{
v10 = revSBox[v11];
v11 = revSBox[v12];
v12 = revSBox[roundKey[4*(i-1)]];
v9 = revSBox[roundKey[4*(i-1)+1]] ^ para[i>>2];
}
roundKey[i*4] = v9^roundKey[(i-4)*4];
roundKey[i*4+1] = v10^roundKey[(i-4)*4+1];
roundKey[i*4+2] = v11^roundKey[(i-4)*4+2];
roundKey[i*4+3] = v12^roundKey[(i-4)*4+3];
}
}
// 加密过程第一步的异或运算(但是里面的数据还需要思考一下) 传入的参数是数据加密的轮数
void XorIV(uint8_t round)
{
for(int i=0;i<=15;i++)
{
verify[i]^=pass_token[16*round+16+i];
}
}


// 逆字节代换()
void reveSubBytes()
{
for(int i=0; i<16; i++)
{
verify[i] = revSBox[verify[i]];
}

}

// 行移位的逆运算 第一行不移动 第二行循环右移1位
void reveShiftRows()
{
int round = 0;
uint8_t tem = 0;//临时存放值
int j =0;
for (int i=0;i<4;i++)
{
round = i;
while(round)
{
tem = verify[i*4+3];
for(j=3;j>0;j--)
{
verify[i*4+j] = verify[i*4+j-1];
}
verify[i*4+j] = tem;
round--;
}
}
}

// 列混合
// 使用到的矩阵
static const uint8_t deColCinfusion[16] =
{
0xe, 0xb, 0xd, 0x9,
0x9, 0xe, 0xb, 0xd,
0xd, 0x9, 0xe, 0xb,
0xb, 0xd, 0x9, 0xe
};

// GF之中的运算
static uint8_t GFMul2(uint8_t s)
{
uint8_t result = s*2;
int tem = (s*2)&0x00000100;
if(tem != 0)
{
result = result&0xff;
result^= 0x1b;
}
return result;
}

static uint8_t GFMul3(uint8_t s)
{
return GFMul2(s)^s;
}

static uint8_t GFMul4(uint8_t s)
{
return GFMul2(GFMul2(s));
}

static uint8_t GFMul8(uint8_t s)
{
return GFMul2(GFMul4(s));
}

static uint8_t GFMul9(uint8_t s)
{
return GFMul8(s)^s;
}

static uint8_t GFMul11(uint8_t s)
{
return GFMul9(s)^GFMul2(s);
}

static uint8_t GFMul12(uint8_t s)
{
return GFMul8(s)^GFMul4(s);
}

static uint8_t GFMul13(uint8_t s)
{
return GFMul12(s)^s;
}

static uint8_t GFMul14(uint8_t s)
{
return GFMul12(s)^GFMul2(s);
}

static uint8_t GFMul(uint8_t n,uint8_t s)
{
uint8_t result = 0;
if (n==1)
result = s;
else if (n==2) // 2
result = GFMul2(s);
else if (n==3) // 3
result = GFMul3(s);
else if (n==0x9) // 9
result = GFMul9(s);
else if (n==0xb) // 11
result = GFMul11(s);
else if (n==0xd) // 13
result = GFMul13(s);
else if (n==0xe) // 14
result = GFMul14(s);
return result;
}

// 逆列混合

static void deColCinfusions()
{
uint8_t temVerify[16];
uint8_t i =0;
uint8_t j =0;
for(i=0;i<16;i++)
{
temVerify[i] = verify[i];
}

for (i =0;i<4;i++)
{
for(j=0;j<4;j++)
{
verify[i*4+j] = GFMul(deColCinfusion[i*4],temVerify[j])^GFMul(deColCinfusion[i*4+1],temVerify[4+j])^GFMul(deColCinfusion[i*4+2],temVerify[2*4+j])^GFMul(deColCinfusion[i*4+3],temVerify[3*4+j]);
}
}
}

// 轮密钥加(传入的参数是每一轮使用的密钥的第一个数的索引)
static void addRoundKey(uint8_t theIndex)
{
uint8_t i,j = 0;
for(i=0;i<4;i++)
{
for(j=0;j<4;j++)
{
verify[4*i+j]^=roundKey[theIndex+4*j+i];
}
}
}
// 将4*4的矩阵进行转置
static void transMatri(uint8_t* mutrix)
{
uint8_t temMutrix[16];
uint8_t i,j=0;
for(i=0;i<16;i++)
{
temMutrix[i] = mutrix[i];
}
for(i=0;i<4;i++)
{
for(j=0;j<4;j++)
{
mutrix[4*i+j] = temMutrix[i+4*j];
}
}
}

int main(void)
{
// 密钥扩展
expandKeyNums();
uint8_t i,j=0;
printf("verity:");
for(i=0;i<32;i=i+16)
{
for(j=i;j<i+16;j++)
{
verify[j-i] = c[j];
}
// 初始的时候要进行一次转置
transMatri(verify);
//第一次轮密钥加
addRoundKey(16*10);
// 10次解密
for(j=0;j<10;j++)
{
// 逆行移位
reveShiftRows();
// 逆字节代换
reveSubBytes();
if (j==9)
break;
// 轮密钥加密
addRoundKey(16*(9-j));
//逆列混淆
deColCinfusions();

}
// 再进行一次轮密钥加密
addRoundKey(0);
//结束的时候要机进行一次转置
transMatri(verify);
//最后要和IV进行异或运算
XorIV(i/16);
for(j =0;j<16;j++)
{
printf("%c",verify[j]);
}
}
return 0;
}
verity:7026271d7bb5d404d63a72b88e6b4d63

image-20220421134033932

所以flag是 DASCTF{7026271d7bb5d404d63a72b88e6b4d63}