BUUCTF reverse wp 51 - 55
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; // [esp+0h] [ebp-44Ch]CHAR v11[256]; // [esp+54h] [ebp-3F8h] BYREFchar v12[7]; // [esp+154h] [ebp-2F8h] BYREF__int16 v13; // [esp+15Bh] [ebp-2F1h]char v14; // [esp+15Dh] [ebp-2EFh]char Str[253]; // [esp+160h] [ebp-2ECh] BYREF__int16 v16; // [esp+25Dh] [ebp-1EFh]char v17; // [esp+25Fh] [ebp-1EDh]CHAR v18[256]; // [esp+260h] [ebp-1ECh] BYREFCHAR String[4]; // [esp+360h] [ebp-ECh] BYREFint v20; // [esp+364h] [ebp-E8h]__int16 v21; // [esp+368h] [ebp-E4h]CHAR Text[32]; // [esp+36Ch] [ebp-E0h] BYREFstruct tagRECT Rect; // [esp+38Ch] [ebp-C0h] BYREFCHAR Buffer[100]; // [esp+39Ch] [ebp-B0h] BYREFHDC hdc; // [esp+400h] [ebp-4Ch]struct tagPAINTSTRUCT Paint; // [esp+404h] [ebp-48h] BYREFint v27; // [esp+444h] [ebp-8h]int v28; // [esp+448h] [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, "0kk`d1a`55k222k2a776jbfgd`06cjjb");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; // [esp+4Ch] [ebp-24h]CHAR String2[4]; // [esp+50h] [ebp-20h] BYREFBYTE v6[16]; // [esp+54h] [ebp-1Ch] BYREFDWORD pdwDataLen; // [esp+64h] [ebp-Ch] BYREFHCRYPTHASH phHash; // [esp+68h] [ebp-8h] BYREFHCRYPTPROV phProv; // [esp+6Ch] [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?redirectedfrom=MSDN
猜测是经过md5处理, 返回的值与0kk`d1a`55k222k2a776jbfgd`06cjjb ^ SS的结果比较
s = '0kk`d1a`55k222k2a776jbfgd`06cjjb'
key = 'SS'md5val = ''
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; // [esp+4Ch] [ebp-Ch]unsigned int v5; // [esp+54h] [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-kit
apt安装的软件, 可以用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]; // [sp+4h] [bp-208h] BYREFint v3; // [sp+204h] [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: initConnection+8C↑o
.data:0001B108 ; .text:off_10C2C↑o
.data:0001B108 ; "echo.byethost51.com"
在initConnection
函数中进行链接建立操作, 可以分析出端口和地址
import hashlibflag = hashlib.md5(b'echo.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]; // [esp+12h] [ebp-96h] BYREFchar Destination[80]; // [esp+44h] [ebp-64h] BYREFDWORD flOldProtect; // [esp+94h] [ebp-14h] BYREFsize_t v7; // [esp+98h] [ebp-10h]int i; // [esp+9Ch] [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; // [esp+Ch] [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]; // [esp+18h] [ebp-80h] BYREFint i; // [esp+78h] [ebp-20h]int success; // [esp+7Ch] [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]; // [esp+1Ch] [ebp-6Ch] BYREFint v3; // [esp+68h] [ebp-20h]int i; // [esp+6Ch] [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]; // [esp+13h] [ebp-15h] BYREFint v4; // [esp+1Ch] [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("GoldenTicket2018@flare-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]; // [rsp+20h] [rbp-60h] BYREFchar Str1[64]; // [rsp+50h] [rbp-30h] BYREFchar v9[64]; // [rsp+90h] [rbp+10h] BYREFchar v10[64]; // [rsp+D0h] [rbp+50h] BYREFchar Str2[60]; // [rsp+110h] [rbp+90h] BYREFint v12; // [rsp+14Ch] [rbp+CCh] BYREF_main();strcpy(Str2, "EmBmP5Pmn7QcPU4gLYKv5QcMmB3PWHcP5YkPq3=cT6QckkPckoRG");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; // [rsp+34h] [rbp-1Ch]int v9; // [rsp+38h] [rbp-18h]int v11; // [rsp+48h] [rbp-8h]int i; // [rsp+4Ch] [rbp-4h]unsigned __int8 *v13; // [rsp+70h] [rbp+20h]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; // [rsp+Fh] [rbp-11h]int i; // [rsp+14h] [rbp-Ch]const char *v8; // [rsp+30h] [rbp+10h]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 = 'EmBmP5Pmn7QcPU4gLYKv5QcMmB3PWHcP5YkPq3=cT6QckkPckoRG'
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]
相关文章:
BUUCTF reverse wp 51 - 55
findKey shift f12 找到一个flag{}字符串, 定位到关键函数, F5无效, 大概率是有花指令, 读一下汇编 这里连续push两个byte_428C54很奇怪, nop掉下面那个, 再往上找到函数入口, p设置函数入口, 再F5 LRESULT __stdcall sub_401640(HWND hWndParent, UINT Msg, WPARAM wPara…...
WebGL笔记:使用鼠标绘制多个线条应用及绘制动感线性星座
使用鼠标绘制多个线条 多个线条,肯定不是一笔画过的,而是多次画的线条既然是多线,那就需要有个容器来管理它们 1 )建立容器对象 建立一个 lineBox 对象,作为承载多边形的容器 // lineBox.js export default class …...
nodejs+vue 汽车销售系统elementui
第三章 系统分析 10 3.1需求分析 10 3.2可行性分析 10 3.2.1技术可行性:技术背景 10 3.2.2经济可行性 11 3.2.3操作可行性: 11 3.3性能分析 11 3.4系统操作流程 12 3.4.1管理员登录流程 12 3.4.2信息添加流程 12 3.4.3信息删除流程 13 第四章 系统设计与…...
leetcode76 Minimum Window Substring
给定两个字符串s和t, 找到s的一个子串,使得t的每个字符都出现在子串中,求最短的子串 由于要每个字符出现,所以顺序其实没有关系 因此我们可以定义一个map,统计t中字符出现次数 然后在s中慢慢挪动滑动窗口,…...
简单工厂模式~
我们以生产手机作为应用场景展开讲解! 手机是一个抽象的概念,它包含很多的品牌,例如华为,苹果,小米等等,因此我们可将其抽象为一个接口,如下所示: public interface tel {void pro…...
基于Java的会员管理系统设计与实现(源码+lw+部署文档+讲解等)
文章目录 前言具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序(小蔡coding)有保障的售后福利 代码参考源码获取 前言 💗博主介绍:✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作…...
数据结构 图 并查集 遍历方法 最短路径算法 最小生成树算法 简易代码实现
文章目录 前言并查集图遍历方法广度优先遍历深度优先遍历 最小生成树算法Kruskal算法Prim算法 最短路径算法Dijkstra算法BellmanFord算法FloydWarshall算法 全部代码链接 前言 图是真的难,即使这些我都学过一遍,再看还是要顺一下过程;说明方…...
idea Springboot 教师标识管理系统开发mysql数据库web结构java编程计算机网页源码maven项目
一、源码特点 springboot 教师标识管理系统是一套完善的信息系统,结合springboot框架和bootstrap完成本系统,对理解JSP java编程开发语言有帮助系统采用springboot框架(MVC模式开发),系统 具有完整的源代码和数据库&…...
2023-9-30 JZ36 二叉搜索树与双向链表
题目链接:二叉搜索树与双向链表 import java.util.*; /** public class TreeNode {int val 0;TreeNode left null;TreeNode right null;public TreeNode(int val) {this.val val;}} */ public class Solution {TreeNode pre null;public TreeNode Convert(Tree…...
在windows的ubuntu LTS中安装及使用EZ-InSAR进行InSAR数据处理
EZ-InSAR(曾被称为MIESAR,即Matlab界面用于易于使用的合成孔径雷达干涉测量)是一个用MATLAB编写的工具箱,用于通过易于使用的图形用户界面(GUI)进行干涉合成孔径雷达(InSAR)数据处理…...
腾讯mini项目-【指标监控服务重构】2023-08-25
今日已办 traefik proxy jaeger Prometheus prometheus | Prometheus 配置完依然无法实现 web-url的前缀访问【待解决】 Set span storage type : elasticsearch services:elasticsearch:image: elasticsearch:7.17.12container_name: elasticsearchnetworks:- backend # …...
数据挖掘(1)概述
一、数据仓库和数据挖掘概述 1.1 数据仓库的产生 数据仓库与数据挖掘: 数据仓库和联机分析处理技术(存储)。数据挖掘:在大量的数据中心挖掘感兴趣的知识、规则、规律、模式、约束(分析)。数据仓库用于决策分析: 数据仓库:是在数…...
YApi Pro
1.介绍 说明:YApi Pro 是一款高效、易用、功能强大的 API 管理平台,旨在为开发、产品、测试人员提供更优雅的接口管理服务。它可以帮助开发者轻松创建、发布、维护 API,同时为用户提供了优秀的交互体验,开发人员可以更加高效地完…...
AUTOSAR RTE介绍(更新版230925)
RTE是什么 AUTOSAR RTE(Run Time Environment)实现了AUTOSAR系统中的虚拟功能总线(VFB),提供了SWC(Software Component)之间的访问接口和SWC对于BSW资源的访问接口。RTE为SWC中的Runnable提供与其他SWC或者BSW模块通信的接口,RTE将Runnable映射到OS Task中,并且管理Runna…...
深度学习笔记_1、定义神经网络
1、使用了PyTorch的nn.Module类来定义神经网络模型;使用nn.Linear来创建全连接层。(CPU) import torch.nn as nn import torch.nn.functional as F from torchsummary import summary# 定义神经网络模型 class Net(nn.Module):def __init__(self):super(Net, self).__init__()…...
【Java 进阶篇】MySQL 事务详解
在数据库管理中,事务是一组SQL语句的执行单元,它们被视为一个整体。事务的主要目标是保持数据库的一致性和完整性,即要么所有SQL语句都成功执行,要么所有SQL语句都不执行。在MySQL中,事务起到了非常重要的作用…...
Spring修炼之旅(3)自动装配与注解开发
一、自动装配说明 1.1概述 自动装配是使用spring满足bean依赖的一种方法 spring会在应用上下文中为某个bean寻找其依赖的bean。 1.2装配机制 Spring中bean有三种装配机制,分别是: 在xml中显式配置; 在java中显式配置; 隐式…...
嵌入式Linux应用开发-基础知识-第十六章GPIO和Pinctrl子系统的使用
嵌入式Linux应用开发-基础知识-第十六章GPIO和Pinctrl子系统的使用 第十六章 GPIO 和 Pinctrl 子系统的使用16.1 Pinctrl 子系统重要概念16.1.1 引入16.1.2 重要概念16.1.3 示例16.1.4 代码中怎么引用pinctrl 16.2 GPIO子系统重要概念16.2.1 引入16.2.2 在设备树中指定引脚16.2…...
Ubuntu系统下使用apt-get安装Mysql8
记录一下在Ubuntu20.04 64位系统下面使用apt-get方式安装mysql8关系型数据库 Centos下使用yum安装Mysql8(Mysql5.7)以及常见的配置和使用 首先肯定是检查下当前Ubuntu系统是否已经安装过mysql数据库 一般拿到新的云服务器是没有安装的 rootmyw:~# whe…...
jenkins联动显示或隐藏参数
1. 添加组件 Active Choices Plug-in 如jenkins无法联网,可在以下两个地址中下载插件,然后放到/home/jenkins/.jenkins/plugin下面重启jenkins即可 Active Choices Active Choices | Jenkins plugin 2. 效果如下: sharding为空时…...
Error: Activity class {xxx.java} does not exist
git切换到不同的branch之后,报下面的错误: Error: Activity class {xxx.java} does not exist 解决方案: 首先clean 然后会删除build目录 然后点击:Invalidate Caches Android Studio重启,然后重新build即可。...
保护模式阶段测试-模拟3环0环调用
保护模式阶段测试-模拟3环0环调用 最近又复习了一下保护模式相关的内容,然后打算搞个能够把段页的大部分知识能够串联起来的测试代码 最终想到的一个项目如下: 三环部分: 0.编写一个函数读取高2g的地址内容 1.通过设备通信到0环告诉0环我新…...
Dart笔记:stream_channel 包用法
标题1 标题2 作者:李俊才 (jcLee95):https://blog.csdn.net/qq_28550263 邮箱 :291148484163.com 本文地址:https://blog.csdn.net/qq_28550263/article/details/133426961 【介绍】stream_channel是一个用…...
Java进阶必会JVM-深入浅出Java虚拟机
系列文章目录 送书第一期 《用户画像:平台构建与业务实践》 送书活动之抽奖工具的打造 《获取博客评论用户抽取幸运中奖者》 送书第二期 《Spring Cloud Alibaba核心技术与实战案例》 送书第三期 《深入浅出Java虚拟机》 文章目录 系列文章目录前言一、推荐书籍二…...
1200*B. Sorted Adjacent Differences(构造)
Problem - 1339B - Codeforces 解析: 题目要求每相邻两个值差的绝对值相等或递增。 先排序,可以想到我们先取两侧的数肯定相距最远,然后靠中心每次取两个数,这样符合题目要求。 直接遍历,先取的是答案靠后的数据&…...
恼人的TCP套接字部分发送成功场景
源起 以前就知道套接字有可能出现部分发送成功的可能,直到近段时间一个典型的使用场景触发了明确的此问题,才予以重视,比较深入地考虑解决这个问题的方案! 分析 因为TCP的流式特征,如果出现部分发送成功,…...
ROS2 中的轻量级、自动化、受控回放
一、说明 这篇文章描述了一种在 ROS2 中实现受控重播器的轻量级方法。用以测试中将现象重新播放一遍,以实现调参或故障定位的目的。所有源代码都可以在这里找到。该帖子也可在此处获得。 二、问题:不同步重播 任何曾经认真开发过 ROS2 的人都会知道这个问…...
Egg使用jwt拦截jtoken验证
安装 npm install egg-jwt注册插件 在config文件夹子下 plugin,js下 use strict;module.exports {//mysqlmysql: {enable: true,package: egg-mysql},//jwtjwt: {enable: true,package: egg-jwt} };使用中间件 在app文件下创建 middleware 文件夹 在middleware 文件下创建…...
装饰器模式详解和实现(设计模式 二)
装饰器模式(Decorator Pattern)是一种结构型设计模式,它允许你动态地将对象添加到现有对象中,以提供额外的功能,同时又不影响其他对象。 实现示例 1.定义一个接口或抽象类,表示被装饰对象的公共接口 //抽…...
面试问到MySQL模块划分与架构体系怎么办
面试问到Mysql模块划分与架构体系怎么办 文章目录 1. 应用层连接管理器(Connection Manager)安全性和权限模块(Security and Privilege Module) 2. MySQL服务器层2.1. 服务支持和工具集2.2. SQL Interface2.3. 解析器举个解析器 …...
导航网站备案/抚顺网站seo
被坑惨。 以下几点注意: 1.设置CLASSPATH环境变量时一定要加上 ‘.。(也就是 点 这个英文符号 表示当前目录),否则所有的执行命令都无法执行。 2.设置好环境变量之后一定要重启cmd命令窗口才能生效。(被坑惨&#…...
老牛wordpress/如何做一个自己的网站
1、说明: 1.1、known_hosts是什么? ssh会把你每个你访问过计算机的公钥(public key)都记录在~/.ssh/known_hosts。当下次访问相同计算机时,OpenSSH会核对公钥。如果公钥不同,OpenSSH会发出警告, 避免你受到DNS Hijac…...
网站建设行吗/小说搜索风云榜
1.更改背景图片 如果希望将登录放置在初始屏幕右侧,请按如下处理: 使用事务 SWM0 可以在数据库中创建自己的图像.选择选项"二进制数据". 可以按.GIF 格式保存图像. 使用表 SSM_CUST 中的关键字 "START_IMAGE" 创建数据记录. (使用…...
南京建设银行网站/搜索量用什么工具查询
1.第一种方式: using SQLDMO;//Microsoft SQLDMO Object Library 8.0 /// <summary>/// 数据库的备份/// 涂聚文注:数据库的备份和实时进度显示代码:(远程备份在数据库原本地,如果在数据库安装的电脑上备份,就可以自行选择文件夹地址,不能备份在客户端的电脑上…...
网站地图咋做/惠州seo网络推广
注意:修饰键(如)后跟多个按键的情况表示在按住修饰键的情况下依次按下相应键。打开/前往T前往文件P前往项目R前往 methodP命令提示G前往行KB开关侧栏 python 控制台N新建窗口编辑L选择行 (重复按下将下一行加入选择)D选择词 (重复按下时多重选…...
设计广告公司网站建设/百度推广找谁做
先占个坑,这个方面的“道”“术”杂糅,而且相当个人化。...