重庆未来科技网站建设,安徽网站制作,政务网站队伍建设情况,中文网站欣赏findKey shift f12 找到一个flag{}字符串, 定位到关键函数, F5无效, 大概率是有花指令, 读一下汇编 这里连续push两个byte_428C54很奇怪, nop掉下面那个, 再往上找到函数入口, p设置函数入口, 再F5
LRESULT __stdcall sub_401640(HWND hWndParent, UINT Msg, WPARAM wPara…findKey shift f12 找到一个flag{}字符串, 定位到关键函数, F5无效, 大概率是有花指令, 读一下汇编 这里连续push两个byte_428C54很奇怪, nop掉下面那个, 再往上找到函数入口, p设置函数入口, 再F5
LRESULT __stdcall sub_401640(HWND hWndParent, UINT Msg, WPARAM wParam, LPARAM lParam)
{int v5; // eaxsize_t v6; // eaxDWORD v7; // eaxint v8; // eaxint v9; // eaxCHAR *v10; // [esp0h] [ebp-44Ch]CHAR v11[256]; // [esp54h] [ebp-3F8h] BYREFchar v12[7]; // [esp154h] [ebp-2F8h] BYREF__int16 v13; // [esp15Bh] [ebp-2F1h]char v14; // [esp15Dh] [ebp-2EFh]char Str[253]; // [esp160h] [ebp-2ECh] BYREF__int16 v16; // [esp25Dh] [ebp-1EFh]char v17; // [esp25Fh] [ebp-1EDh]CHAR v18[256]; // [esp260h] [ebp-1ECh] BYREFCHAR String[4]; // [esp360h] [ebp-ECh] BYREFint v20; // [esp364h] [ebp-E8h]__int16 v21; // [esp368h] [ebp-E4h]CHAR Text[32]; // [esp36Ch] [ebp-E0h] BYREFstruct tagRECT Rect; // [esp38Ch] [ebp-C0h] BYREFCHAR Buffer[100]; // [esp39Ch] [ebp-B0h] BYREFHDC hdc; // [esp400h] [ebp-4Ch]struct tagPAINTSTRUCT Paint; // [esp404h] [ebp-48h] BYREFint v27; // [esp444h] [ebp-8h]int v28; // [esp448h] [ebp-4h]LoadStringA(hInstance, 0x6Au, Buffer, 100);if ( Msg 0x111 ){if ( Msg 517 ){if ( strlen((const char *)String1) 6 )ExitProcess(0);if ( strlen((const char *)String1) ){memset(v18, 0, sizeof(v18));v6 strlen((const char *)String1);memcpy(v18, String1, v6);v7 strlen((const char *)String1);sub_40101E(String1, v7, v10);strcpy(Str, 0kkd1a55k222k2a776jbfgd06cjjb);memset(Str[33], 0, 0xDCu);v16 0;v17 0;strcpy(v12, SS);*(_DWORD *)v12[3] 0;v13 0;v14 0;v8 strlen(Str);sub_401005(v12, (int)Str, v8);if ( _strcmpi((const char *)String1, Str) ){SetWindowTextA(hWndParent, flag{});MessageBoxA(hWndParent, Are you kidding me?, ^_^, 0);ExitProcess(0);}memcpy(v11, unk_423030, 0x32u);v9 strlen(v11);sub_401005(v18, (int)v11, v9);MessageBoxA(hWndParent, v11, 0, 0x32u);}dword_428D54;}else{if ( Msg ! 520 )return DefWindowProcA(hWndParent, Msg, wParam, lParam);if ( dword_428D54 16 ){strcpy(String, ctf);v20 0;v21 0;SetWindowTextA(hWndParent, String);strcpy(Text, Are you kidding me?);MessageBoxA(hWndParent, Text, Buffer, 0);}dword_428D54;}}else{switch ( Msg ){case 0x111u:v28 (unsigned __int16)wParam;v27 HIWORD(wParam);if ( (unsigned __int16)wParam 104 ){DialogBoxParamA(hInstance, (LPCSTR)0x67, hWndParent, (DLGPROC)DialogFunc, 0);}else{if ( (unsigned __int16)wParam ! 105 )return DefWindowProcA(hWndParent, Msg, wParam, lParam);DestroyWindow(hWndParent);}break;case 2u:PostQuitMessage(0);break;case 0xFu:hdc BeginPaint(hWndParent, Paint);GetClientRect(hWndParent, Rect);v5 strlen(Buffer);DrawTextA(hdc, Buffer, v5, Rect, 1u);EndPaint(hWndParent, Paint);break;default:return DefWindowProcA(hWndParent, Msg, wParam, lParam);}}return 0;
}int __cdecl sub_4013A0(BYTE *pbData, DWORD dwDataLen, LPSTR lpString1)
{DWORD i; // [esp4Ch] [ebp-24h]CHAR String2[4]; // [esp50h] [ebp-20h] BYREFBYTE v6[16]; // [esp54h] [ebp-1Ch] BYREFDWORD pdwDataLen; // [esp64h] [ebp-Ch] BYREFHCRYPTHASH phHash; // [esp68h] [ebp-8h] BYREFHCRYPTPROV phProv; // [esp6Ch] [ebp-4h] BYREFif ( !CryptAcquireContextA(phProv, 0, 0, 1u, 0xF0000000) )return 0;if ( CryptCreateHash(phProv, 0x8003u, 0, 0, phHash) ){if ( CryptHashData(phHash, pbData, dwDataLen, 0) ){CryptGetHashParam(phHash, 2u, v6, pdwDataLen, 0);*lpString1 0;for ( i 0; i pdwDataLen; i ){wsprintfA(String2, %02X, v6[i]);lstrcatA(lpString1, String2);}CryptDestroyHash(phHash);CryptReleaseContext(phProv, 0);return 1;}else{CryptDestroyHash(phHash);CryptReleaseContext(phProv, 0);return 0;}}else{CryptReleaseContext(phProv, 0);return 0;}
}发现string1会经过sub_4013A0中的hash处理, 查MSDN的文档 https://docs.microsoft.com/en-us/windows/win32/seccrypto/alg-id?redirectedfromMSDN 猜测是经过md5处理, 返回的值与0kkd1a55k222k2a776jbfgd06cjjb ^ SS的结果比较
s 0kkd1a55k222k2a776jbfgd06cjjb
key SSmd5val
for i in range(len(s)):md5val chr(ord(s[i]) ^ ord(key[i % 2]))print(md5val)查MD5, 得到解密真正flag的key 123321
unsigned int __cdecl sub_401590(LPCSTR lpString, int a2, unsigned int a3)
{unsigned int result; // eaxunsigned int i; // [esp4Ch] [ebp-Ch]unsigned int v5; // [esp54h] [ebp-4h]v5 lstrlenA(lpString);for ( i 0; ; i ){result i;if ( i a3 )break;*(_BYTE *)(i a2) ^ lpString[i % v5];}return result;
}shift e导出unk_423030数据, 写逆
enc [87, 94, 82, 84, 73, 95, 1, 109, 105, 70, 2, 110, 95, 2, 108, 87, 91, 84, 76
]
key 123321
flag for i in range(len(enc)):flag chr(enc[i] ^ ord(key[i % 6]))print(flag)firmware
$ file 51475f91-7b90-41dd-81a3-8b82df4f29d0.bin
51475f91-7b90-41dd-81a3-8b82df4f29d0.bin: firmware 941 v7 TP-LINK Technologies ver. 1.0, version 3.15.36, 4063744 bytes or less, at 0x200 772784 bytes , at 0x100000 2883584 bytes$ binwalk -e 51475f91-7b90-41dd-81a3-8b82df4f29d0.bin$ ls _51475f91-7b90-41dd-81a3-8b82df4f29d0.bin.extracted/
120200.squashfs 20400 20400.7z squashfs-root包含一个squashfs文件系统镜像, 需要使用firmware-mod-kit工具包内的unsquashfs_all.sh解压文件系统镜像 需要在linux里编译, 而且安装过程也比较坑, 嫌麻烦的直接上kali
git clone https://github.com/mirror/firmware-mod-kit.git
sudo apt-get install build-essential zlib1g-dev libz1zma-dev python-magic
cd firmware-mod-kit/src
./configure make kali执行
sudo apt update
sudo apt upgrade
sudo apt install firmware-mod-kitapt安装的软件, 可以用dpkg -L xxx显示安装路径, 然后用unsquashfs_all.sh解析文件系统
┌──(kali㉿kali)-[~/Desktop]
└─$ /opt/firmware-mod-kit/trunk/unsquashfs_all.sh 120200.squashfs
Attempting to extract SquashFS 4.X file system...Skipping squashfs-2.1-r2 (wrong version)...
Skipping squashfs-3.0 (wrong version)...
Skipping squashfs-3.0-lzma-damn-small-variant (wrong version)...
Skipping others/squashfs-2.0-nb4 (wrong version)...
Skipping others/squashfs-2.2-r2-7z (wrong version)...
Skipping others/squashfs-3.0-e2100 (wrong version)...
Skipping others/squashfs-3.2-r2 (wrong version)...
Skipping others/squashfs-3.2-r2-lzma (wrong version)...
Skipping others/squashfs-3.2-r2-lzma/squashfs3.2-r2/squashfs-tools (wrong version)...
Skipping others/squashfs-3.2-r2-hg612-lzma (wrong version)...
Skipping others/squashfs-3.2-r2-wnr1000 (wrong version)...
Skipping others/squashfs-3.2-r2-rtn12 (wrong version)...
Skipping others/squashfs-3.3 (wrong version)...
Skipping others/squashfs-3.3-lzma/squashfs3.3/squashfs-tools (wrong version)...
Skipping others/squashfs-3.3-grml-lzma/squashfs3.3/squashfs-tools (wrong version)...
Skipping others/squashfs-3.4-cisco (wrong version)...
Skipping others/squashfs-3.4-nb4 (wrong version)...Trying ./src/others/squashfs-4.2-official/unsquashfs... Parallel unsquashfs: Using 4 processorsTrying ./src/others/squashfs-4.2/unsquashfs... Parallel unsquashfs: Using 4 processorsTrying ./src/others/squashfs-4.0-lzma/unsquashfs-lzma... Parallel unsquashfs: Using 4 processors
480 inodes (523 blocks) to write[| ] 454/523 86%
created 341 files
created 39 directories
created 70 symlinks
created 0 devices
created 0 fifos
File system sucessfully extracted!
MKFS./src/others/squashfs-4.0-lzma/mksquashfs-lzma提取出文件系统中的内容后, 把各个目录翻一遍, 找到backdoor文件
查壳发现UPX
直接 kali 脱壳
┌──(kali㉿kali)-[~/Desktop/squashfs-root/tmp]
└─$ upx -d backdoor Ultimate Packer for eXecutablesCopyright (C) 1996 - 2020
UPX 3.96 Markus Oberhumer, Laszlo Molnar John Reiser Jan 23rd 2020File size Ratio Format Name-------------------- ------ ----------- -----------54907 - 19508 35.53% linux/arm backdoorUnpacked 1 file.拖进IDA
bool initConnection()
{char *v0; // r0char s[512]; // [sp4h] [bp-208h] BYREFint v3; // [sp204h] [bp-8h]memset(s, 0, sizeof(s));if ( mainCommSock ){close(mainCommSock);mainCommSock 0;}if ( currentServer )currentServer;elsecurrentServer 0;strcpy(s, (commServer)[currentServer]);v3 36667;if ( strchr(s, 58) ){v0 strchr(s, 58);v3 atoi(v0 1);*strchr(s, 58) 0;}mainCommSock socket(2, 1, 0);return connectTimeout(mainCommSock, s, v3, 30) 0;
}.data:0001B108 E4 19 01 00 commServer DCD aEchoByethost51 ; DATA XREF: initConnection8C↑o
.data:0001B108 ; .text:off_10C2C↑o
.data:0001B108 ; echo.byethost51.com在initConnection函数中进行链接建立操作, 可以分析出端口和地址
import hashlibflag hashlib.md5(becho.byethost51.com:36667)
print(flag{ flag.hexdigest() })[网鼎杯 2020 青龙组]jocker // positive sp value has been detected, the output may be wrong!
int __cdecl main(int argc, const char **argv, const char **envp)
{char Str[50]; // [esp12h] [ebp-96h] BYREFchar Destination[80]; // [esp44h] [ebp-64h] BYREFDWORD flOldProtect; // [esp94h] [ebp-14h] BYREFsize_t v7; // [esp98h] [ebp-10h]int i; // [esp9Ch] [ebp-Ch]__main();puts(please input you flag:);if ( !VirtualProtect(encrypt, 0xC8u, 4u, flOldProtect) )exit(1);scanf(%40s, Str);v7 strlen(Str);if ( v7 ! 24 ){puts(Wrong!);exit(0);}strcpy(Destination, Str);wrong(Str);omg(Str);for ( i 0; i 186; i )*((_BYTE *)encrypt i) ^ 0x41u;if ( encrypt(Destination) )finally(Destination);return 0;
}char *__cdecl wrong(char *a1)
{char *result; // eaxint i; // [espCh] [ebp-4h]for ( i 0; i 23; i ){result a1[i];if ( (i 1) ! 0 )a1[i] - i;elsea1[i] ^ i;}return result;
}int __cdecl omg(char *str)
{int testval[24]; // [esp18h] [ebp-80h] BYREFint i; // [esp78h] [ebp-20h]int success; // [esp7Ch] [ebp-1Ch]success 1;qmemcpy(testval, unk_4030C0, sizeof(testval));for ( i 0; i 23; i ){if ( str[i] ! testval[i] )success 0;}if ( success 1 )return puts(hahahaha_do_you_find_me?);elsereturn puts(wrong ~~ But seems a little program);
}wrong和omg函数逻辑很简单, 测试的数组也是硬编码的, 不过逆回去之后会发现是假的flag, 所以关键处理逻辑就是encrypt函数了 main函数虽然SP不对, 但是IDA7.7可以直接F5, 大概看一下逻辑也能看懂, 只有encrypt函数不能反编译, 因为上面的for循环是做代码修改的, 可以IDAPython修改回去; 也可以动调然后dump出来
拿到dump得到exe, 拖进IDA分析encrypt
int __cdecl start(int a1)
{int v2[19]; // [esp1Ch] [ebp-6Ch] BYREFint v3; // [esp68h] [ebp-20h]int i; // [esp6Ch] [ebp-1Ch]v3 1;qmemcpy(v2, unk_403040, sizeof(v2));for ( i 0; i 18; i ){if ( (char)(*(_BYTE *)(i a1) ^ aHahahahaDoYouF[i]) ! v2[i] ){puts(wrong ~);v3 0;exit(0);}}puts(come here);return v3;
}就是和aHahahahaDoYouF数组进行xor, 直接REV
#include iostream
#include string
using namespace std;unsigned char testvals[]
{14, 0, 0, 0, 13, 0, 0, 0, 9, 0, 0, 0, 6, 0, 0, 0, 19, 0, 0, 0, 5, 0, 0, 0, 88, 0, 0, 0, 86, 0, 0, 0, 62, 0, 0, 0, 6, 0, 0, 0, 12, 0, 0, 0, 60, 0, 0, 0, 31, 0, 0, 0, 87, 0, 0, 0, 20, 0, 0, 0, 107, 0, 0, 0, 87, 0, 0, 0, 89, 0, 0, 0, 13, 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, 102, 0, 0, 0, 107, 0, 0, 0, 99, 0, 0, 0, 100, 0, 0, 0, 127, 0, 0, 0, 97, 0, 0, 0, 103, 0, 0, 0, 100, 0, 0, 0, 59, 0, 0, 0, 86, 0, 0, 0, 107, 0, 0, 0, 97, 0, 0, 0, 123, 0, 0, 0, 38, 0, 0, 0, 59, 0, 0, 0, 80, 0, 0, 0, 99, 0, 0, 0, 95, 0, 0, 0, 77, 0, 0, 0, 90, 0, 0, 0, 113, 0, 0, 0, 12, 0, 0, 0, 55, 0, 0, 0, 102, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};int main()
{char xorvals[] hahahaha_do_you_find_me?;string flag ;for (int i 0; i 19; i){flag xorvals[i] ^ testvals[i * 4];}cout flag endl;
}但是只有19位, 还差5位, 在dump出来的程序中再找找发现sub_40159A函数
int __cdecl sub_40159A(int a1)
{unsigned int v1; // eaxchar v3[9]; // [esp13h] [ebp-15h] BYREFint v4; // [esp1Ch] [ebp-Ch]strcpy(v3, %tp:);v1 time(0);srand(v1);v4 rand() % 100;v3[6] 0;*(_WORD *)v3[7] 0;if ( (v3[(unsigned __int8)v3[5]] ! *(_BYTE *)((unsigned __int8)v3[5] a1)) v4 )return puts(Really??? Did you find it?OMG!!!);elsereturn puts(I hide the last part, you will not succeed!!!);
}没啥固定逻辑, 剩下5位就摁猜, 因为知道最后一个字符是}, 然后v3 %tp:, 盲猜也是xor, 而且: ^ } 71
#include iostream
#include string
using namespace std;int main()
{char xorvals[] \%tp:;string flag flag{d07abccf8a410c;for (int i 0; i 5; i){flag xorvals[i] ^ 71;}cout flag endl;
}[FlareOn5]Minesweeper Championship Registration
jadx打开, 看到InviteValidator
package defpackage;import java.awt.Component;
import javax.swing.JOptionPane;/* renamed from: InviteValidator reason: default package */
public class InviteValidator {public static void main(String[] args) {String response JOptionPane.showInputDialog((Component) null, Enter your invitation code:, Minesweeper Championship 2018, 3);if (response.equals(GoldenTicket2018flare-on.com)) {JOptionPane.showMessageDialog((Component) null, Welcome to the Minesweeper Championship 2018!\nPlease enter the following code to the ctfd.flare-on.com website to compete:\n\n response, Success!, -1);} else {JOptionPane.showMessageDialog((Component) null, Incorrect invitation code. Please try again next year., Failure, 0);}}
}[羊城杯 2020]easyre int __cdecl main(int argc, const char **argv, const char **envp)
{int v3; // eaxint v4; // eaxint v5; // eaxchar Str[48]; // [rsp20h] [rbp-60h] BYREFchar Str1[64]; // [rsp50h] [rbp-30h] BYREFchar v9[64]; // [rsp90h] [rbp10h] BYREFchar v10[64]; // [rspD0h] [rbp50h] BYREFchar Str2[60]; // [rsp110h] [rbp90h] BYREFint v12; // [rsp14Ch] [rbpCCh] BYREF_main();strcpy(Str2, EmBmP5Pmn7QcPU4gLYKv5QcMmB3PWHcP5YkPq3cT6QckkPckoRG);puts(Hello, please input your flag and I will tell you whether it is right or not.);scanf(%38s, Str);if ( strlen(Str) ! 38|| (v3 strlen(Str), (unsigned int)encode_one(Str, v3, v10, v12))|| (v4 strlen(v10), (unsigned int)encode_two(v10, v4, v9, v12))|| (v5 strlen(v9), (unsigned int)encode_three(v9, v5, Str1, v12))|| strcmp(Str1, Str2) ){printf(Something wrong. Keep going.);return 0;}else{puts(you are right!);return 0;}
}__int64 __fastcall encode_one(char *a1, int a2, char *a3, int *a4)
{int v5; // esiint v6; // esiint v7; // esiint v8; // [rsp34h] [rbp-1Ch]int v9; // [rsp38h] [rbp-18h]int v11; // [rsp48h] [rbp-8h]int i; // [rsp4Ch] [rbp-4h]unsigned __int8 *v13; // [rsp70h] [rbp20h]v13 (unsigned __int8 *)a1;if ( !a1 || !a2 )return 0xFFFFFFFFi64;v11 0;if ( a2 % 3 )v11 3 - a2 % 3;v9 a2 v11;v8 8 * (a2 v11) / 6;for ( i 0; i v9; i 3 ){*a3 alphabet[(char)*v13 2];if ( a2 v11 - 3 i v11 ){if ( v11 1 ){v5 (char)cmove_bits(*v13, 6u, 2u);a3[1] alphabet[v5 (char)cmove_bits(v13[1], 0, 4u)];a3[2] alphabet[(char)cmove_bits(v13[1], 4u, 2u)];a3[3] 61;}else if ( v11 2 ){a3[1] alphabet[(char)cmove_bits(*v13, 6u, 2u)];a3[2] 61;a3[3] 61;}}else{v6 (char)cmove_bits(*v13, 6u, 2u);a3[1] alphabet[v6 (char)cmove_bits(v13[1], 0, 4u)];v7 (char)cmove_bits(v13[1], 4u, 2u);a3[2] alphabet[v7 (char)cmove_bits(v13[2], 0, 6u)];a3[3] alphabet[v13[2] 0x3F];}a3 4;v13 3;}if ( a4 )*a4 v8;return 0i64;
}__int64 __fastcall encode_two(const char *a1, int a2, char *a3, int *a4)
{if ( !a1 || !a2 )return 0xFFFFFFFFi64;strncpy(a3, a1 26, 0xDui64);strncpy(a3 13, a1, 0xDui64);strncpy(a3 26, a1 39, 0xDui64);strncpy(a3 39, a1 13, 0xDui64);return 0i64;
}__int64 __fastcall encode_three(const char *a1, int a2, char *a3, int *a4)
{char v5; // [rspFh] [rbp-11h]int i; // [rsp14h] [rbp-Ch]const char *v8; // [rsp30h] [rbp10h]v8 a1;if ( !a1 || !a2 )return 0xFFFFFFFFi64;for ( i 0; i a2; i ){v5 *v8;if ( *v8 || v5 Z ){if ( v5 || v5 z ){if ( v5 / || v5 9 )*a3 v5;else*a3 (v5 - 0 3) % 10 0;}else{*a3 (v5 - a 3) % 26 a;}}else{*a3 (v5 - A 3) % 26 A;}a3;v8;}return 0i64;
}从后往前逆, encode_three是数字和字母移位置换3位, encode_two是每13位数据进行置换, encode_one是base64(看alphabet猜的) REV
import base64testval EmBmP5Pmn7QcPU4gLYKv5QcMmB3PWHcP5YkPq3cT6QckkPckoRG
print(len(testval))
testval list(testval)for i in range(len(testval)):tmp testval[i]if not str.isalnum(tmp): continueif str.isalpha(tmp):if str.isupper(tmp):testval[i] chr(((ord(tmp) - ord(A) - 3) % 26) ord(A))else:testval[i] chr(((ord(tmp) - ord(a) - 3) % 26) ord(a))else:testval[i] chr(((ord(tmp) - ord(0) - 3) % 10) ord(0))print(.join(testval))tempval [ for _ in range(52)]
tempval[13:26] testval[39:]
tempval[39:] testval[26:39]
tempval[:13] testval[13:26]
tempval[26:39] testval[:13]print(tempval)
tempval .join(tempval)
print(tempval)
flag base64.b64decode(tempval.encode(utf-8))
print(flag.decode(utf-8))注意 - 写脚本时踩的坑: %的优先级大于-; python3解码base64时, 字符都为unicode编码, 而b64decode函数的参数为byte类型, 所以必须先转码. 还有如果用列表的切片赋值, 会出错, 原因在于浅拷贝, 比如
tempval testval
testval[13:26] tempval[39:]
testval[39:] tempval[26:39]
testval[:13] tempval[13:26]
testval[26:39] tempval[:13]