ctf 逆向 专题题解

news2024/9/23 19:21:08

本文的目标是,记录一些不具备通用性的,或者比较进阶的题目。之前的另一篇文章则用于记录一些基础知识和通用性较强的基本手法。

文章目录

  • 跨科题目
    • buu fungame:reverse与pwn的结合
    • reverse+web
  • 反跟踪
    • Easyhook:hook例题
  • vm类型总结
    • 一道稍特殊的vm:js
  • angr进阶
    • 例题:华为杯第一届研究生网络安全创新大赛 infantvm
    • angr的能力范围
  • 花指令
    • push+ret=jmp
    • call+pop=jmp
    • 其它patch时常见的花指令
  • 双进程保护
  • mfc
  • tea模板
  • rc4模板
  • 文件patch把代码写到哪
  • 附录
    • python循环移位
    • 黑盒穷举
    • 2023 ciscn感想

跨科题目

buu fungame:reverse与pwn的结合

从please input开始分析,是一个基本的字符串异或。输入后,程序退出。总感觉少了点啥,怀疑有其它代码偷偷执行了。
浏览了一下左边的函数,感觉是用户函数,但不知道是什么时候调用的。注意到一个b64串,解出来后是also pwn,这其实算是比较明显的提示了。
关键函数是下面这个,copy了两次,两个dst的区别就是容量。src的长度为16,此处存在栈溢出。

int __cdecl sub_4013BA(char *Source)
{
  char Destination[12]; // [esp+1Ch] [ebp-Ch] BYREF

  strcpy(Destination, Source);
  strcpy(x, Source);
  return 0;
}

reverse+web

例题非常简单,就是创建client、然后把flag发送到对面。如果按rev的思维进行调试(看内存、或插入print语句),做起来非常不顺。可以用“nc -l -p 端口号”监听本机端口,然后再尝试发起连接即可。

反跟踪

Easyhook:hook例题

攻防世界EASYHOOK。本题将writeFile hook为加密函数+writeFile。
本题的流程是:

  • 用getProcAddress从指定的DLL(第一个参数,可以来源于loadLibrary)检索被hook函数的地址(第二个参数)。
  • 保存被hook函数地址原来的内容(一般为jmp xxx)。
  • 计算自定义函数地址和被hook函数地址的差。
  • 将被hook函数地址的内容改为“jmp 上一步计算的差”。具体的操作是GetCurrentProcessId、OpenProcess、VirtualProtectEx、WriteProcessMemory。
  • 自定义函数中往往会包含被hook函数(这样比较隐蔽),采用自定义逻辑-去除hook-被hook函数的结构。如果不去除hook,会死循环自定义逻辑。去除hook的具体操作是将先前保存的原内容写回,写回的api还是上述四个。

hook可以避免关键函数显示在调用图里。用户函数较少时,都看一遍就能找到关键函数了。保护作用有限。只是做题的话,只需要关心加密函数、check函数等,看见异或或者求模基本八九不离十了。

vm类型总结

vm的题目,第一步angr,第二步找指令序列。然后是指令翻译。
例题:GWCTF2019 babyvm,

vm的好处就是隐藏实际执行的代码,所以假flag是比较常见的,看见没有执行的关键函数,也要理所当然认为它是执行了的。跑angr的时候有一个实际问题,就是ida地址和实际地址的不同。目前的归纳经验是以0x400000作为base(elf 64符合此规律)。

找指令序列的时候有一个实际问题,怎么找?目前的归纳经验是:

  • 寻找data段的长数据。夹杂了一些0的字节序列,并且为了方便,指令的编码通常是连号的(比如0xE1表示加法,0xE2表示减法)。
  • 其所在函数的结构往往是,将eip设为指令序列起始地址,循环体{单指令函数}(退出条件是eip=终结指令,终结指令会在指令序列的末尾)。
  • 单指令函数中,往往会出现将内存作为函数来执行的代码。其逻辑可能是遍历函数表,判断eip指令与当前函数表表项是否相同,相同则执行对应函数。

指令翻译的时候,也有一些归纳经验。

  • 寄存器和内存之间需要有数据交流,也就是读写函数。寄存器往往不止一个。读写函数可能会全部封装在一起。
  • 具体被执行的函数里,往往会有一句eip自增。这个可以印证eip所在内存位置的判断,也可以根据自增量来判断指令的长度。

一道稍特殊的vm:js

例题是攻防世界secret string 400。
js的背景知识:

  • 原型。我个人理解有些像父类。属性/方法不存在时,会去原型里找,还找不到就去原型的原型里找。
  • Function(str)。这样可以创建一个callable对象。比如f = Function(“alert(1);”),然后f()就可以调用了。

这题第一关是解压(虽然不解压也能看见格式混乱的代码)。教训是遇到未知bin文件先解压。
js有个特殊的地方,就是能进行源码级别的编辑。做js题,找到源码就是成功了一大半。在源码中加入console.log,然后用浏览器运行。不动调很难做出。
对这一题来说,可以看见虚拟机运行的每一条指令(本题是通过eval(字符串)和Function(字符串)执行自定义函数,所以可以在执行前console log),这使得它不那么像一道虚拟机题了。

angr进阶

angr的最简单使用一般的wp都会有,一般是二十行代码左右。
我认为,angr理论上可以媲美ollydbg,至少是linux elf的ollydbg。但实际使用中,其泛用性似乎远远不如od。angr失败的原因是什么?
除了环境/架构支持问题,主要是两个,一个是状态爆炸,另一个是信息不足。
状态爆炸的体现,就是一直不出结果。
信息不足的体现,就是一堆warning,然后很快提醒你not found。

这两个问题,其实是有解决方法的。局部分析可以避免状态爆炸;利用gdb提供context可以解决信息不足。
“扫描gdb context然后自动生成Angr模拟的状态空间,这样子就可以绕开不重要的、但是Angr会受卡的代码,从某个break stop开始,将变量或者内存符号化,然后使用Angr的SimulatorManger进行单步模拟或者explore探索。配合Instrumentation && hook机制,可以在模拟执行的时候从不同的level搜集想要获得的dynamic trace。只有能够自由地在模拟执行中操控(增删改查)expr和constraint,才算真正入门Angr。”

在这里插入图片描述
CLE负责装载二进制对象以及它所依赖的库,生成地址空间。
claripy是经angr封装后的z3,可以单独拿出来当z3用。
PyVex是中间语言,Angr使用Valgrind的中间语言——VEX来完成这方面的内容。VEX中间语言抽象了几种不同架构间的区别,允许在他们之上进行统一的分析。SimuVEX模块是中间语言VEX执行的模拟器。

API使用概览可以看https://www.cnblogs.com/murkuo/p/15316469.html。
接下来是github的jakespringer/angr_ctf上的十几道例题(dist目录下是题目,solution目录下有答案)。代码我就不贴了,15道rev题的代码都很有参考价值。
00是find的使用,也是网上大多数题解的模样。需要知道成功代码的地址。
01是avoid的使用。avoid用于剪枝。例题里重复执行了很多代码。需要知道导致失败的代码的地址。
02是condition,用于不知道成功/失败代码地址的情况。此外,我认为返回布尔值的函数有很大的自定义空间,而不只是判断“标准输出内容是否等于成功/失败字符串”。
03是手工指定register,使用blank state(而非entry state)来实现任意地址(解题的话一般是用户输入之后)开始执行。blank state一定要指定fill option。例题是一个多输入的题目。
04是栈修复。与03并列,都是对initial state进行自己的设置,03设置initial_state.reg.寄存器名,04设置initial_state.stack。起始地址的选择很重要,应选择在scanf执行完毕、调用者退栈之后。栈修复主要用于输入内容被存储在栈中的情况(严格来说,是初次访问输入时,是通过栈取的)。05的输入内容被存储在常量地址,可以设置initial_state.memory。06的输入内容被存储在malloc的动态地址,也是设置initial_state.memory,但有点绕,因为要先往模拟的指针地址存入指针,然后往指针存入符号变量。
07与之前不同。之前是标准输入。07则是从文件读入。因此需要用angr来模拟一个与代码中fopen内同名的文件。然后从fopen开始执行。
01-07解决的主要是自定义起点时,initial state信息不足的问题,最重要是那个填充选项。从此可以让分析从关键的地方开始。
08-12解决的是状态爆炸问题。08自定义终点(一般定在对用户输入的所有处理结束之后),然后添加一个“处理后的用户输入等于内置结果”的约束。09则利用hook替换中间的某个函数(实际实现相当于范围patch,有时patch掉一个函数call,有时patch掉几行),前提是理解了这个函数的作用,hook应当起到人工给angr减负的作用。10也是hook,但不是汇编行级hook,而是符号级hook(也可以理解为,angr模拟了函数),这是为了应对需要patch的地方过多的情况。11是模拟scanf函数。
12讲了angr的一个选项,veritesting。Veritesting结合了静态符合执行与动态符号执行,减少了路径爆炸的影响。
13则是用angr自己实现的库函数来hook本来的库函数,从而加速执行。还给了一个可替换的库函数的总列表,srand,java的,非常强大。这题的另一个启示是,静态编译能增加函数数量,从而些许增加逆向难度。
14是用call state来对so进行模拟执行。
至于15-17,算是pwn。

例题:华为杯第一届研究生网络安全创新大赛 infantvm

我用网上的angr模板试过,当时结果是无解。在wp里居然看见了angr。多番尝试,我发现了玄学。
如果发现有解,但解明显不是flag(比如\x00),这个时候一定要试,狠狠试。一样的代码也能跑出不同的结果。目前可以确认的是,跟flag长度关系不大(因此可以设成50),跟veritesting也没有关系(开不开都有可能出)。

import angr
import sys
import claripy

path_to_binary = r'C:\Users\ysnb\Downloads\infantvm'  # :string
project = angr.Project(path_to_binary)

# start_address = 0x080492DC
initial_state = project.factory.entry_state(
    # addr=start_address,
    add_options={angr.options.SYMBOL_FILL_UNCONSTRAINED_MEMORY,
                 angr.options.SYMBOL_FILL_UNCONSTRAINED_REGISTERS}
)


class ReplacementScanf(angr.SimProcedure):
    def run(self, format_string, scanf_address):
        scanf = claripy.BVS('scanf', 50*8)
        self.state.memory.store(scanf_address, scanf, endness=project.arch.memory_endness)
        self.state.globals['solution'] = scanf


scanf_symbol = '__isoc99_scanf'
project.hook_symbol(scanf_symbol, ReplacementScanf())
simulation = project.factory.simgr(initial_state, veritesting=True)


def is_successful(state):
    stdout_output = state.posix.dumps(sys.stdout.fileno())
    return b'Good job' in stdout_output  # :boolean


def should_abort(state):
    stdout_output = state.posix.dumps(sys.stdout.fileno())
    return b'Try again' in stdout_output


simulation.explore(find=is_successful, avoid=should_abort)

if simulation.found:
    solution_state = simulation.found[0]
    stored_solution = solution_state.globals['solution']
    solution = solution_state.solver.eval(stored_solution)
    print(solution)
    from Crypto.Util.number import long_to_bytes
    # print(long_to_bytes(solution))
    print(long_to_bytes(solution).decode()[::-1])
else:
    raise Exception('Could not find the solution')

在这里插入图片描述

angr的能力范围

从之前的题目中知道,常量异或肯定能解,
base64能解吗?base58能解吗?
md5能解吗?aes能解吗?

有些情况解决不了,比如:

  • 预期输入的状态数很多,比如输入的flag是字符画
  • 找不到终点(check函数的位置,或者正确提示字符串),比如有壳程序

花指令

keypatch插件可以搜索指定的超过一行的汇编片段。这对花指令分析或许有用。
需要注意的是,如果jmp $+1,实质作用也就成了nop。因此所有的jmp花指令都可以改写为nop花指令。

push+ret=jmp

牢记ret就是pop eip。
例题:ISCTF2022 final。动调的时候会发现,程序通过 “有效代码 + push下一处有效代码位置 + ret” 的方法实现控制流的跳转,每次只执行一句汇编。
这种写法会影响静态分析。解决的方法是,把所有的有效代码 + push + ret组合都patch成有效代码 + far jmp(0xEA)。
自定义patch的时候注意,如果patch成0x90有问题,可以试试patch成0x00。

call+pop=jmp

牢记call就是push+jmp。
判断一个call是不是花指令,主要看操作数。如果是一个在附近的地址,多半是花指令。
例题:ISCTF2022 simpleflower。这里立下一个原则,就是如果超过三处,就应当写脚本来patch了,而不是手改。此处留下一个模式匹配patch的idc代码。

#include <idc.idc>
 
static main()
{
   auto i,j,from,size;
   from=0x00407000; //起始地址
   size=0x0040F201-0x00407000;//扫描数据块大小
 
   for ( i=0; i < size;i++ ) {
 
//查找 EB 03 C3 CD 03  ,替换90
      if ((Byte(from)==0xeB)&&(Byte(from+1)==0x03)&&(Byte(from+2)==0xC3)&&(Byte(from+3)==0xCD)&&(Byte(from+4)==0x03))
     {
           for(j=0;j<5;j++)
          {
               PatchByte(from,0x90);
               from++;
            }
            continue;
       }
       
      //查找 E8 01 00 00 00 E9  ,替换90
      if ((Byte(from)==0xe8)&&(Byte(from+1)==0x01)&&(Byte(from+2)==0x00)&&(Byte(from+3)==0x00)&&(Byte(from+4)==0x00)&&(Byte(from+5)==0xE9))
     {
           for(j=0;j<12;j++)
          {
               PatchByte(from,0x90);
               from++;
            }
            continue;
       }
       //查找 E8 00 00 00 00  call    $+5,替换90
      if ((Byte(from)==0xe8)&&(Byte(from+1)==0x00)&&(Byte(from+2)==0x00)&&(Byte(from+3)==0x00)&&(Byte(from+4)==0x00))
     {
           for(j=0;j<17;j++)
          {
               PatchByte(from,0x90);
               from++;
            }
            continue;
       }
         from++;
    }
    Message("\n" + "OK\n");
 }

本题的花法是:

call $+5 (对应机器码为E8 00 00 00 00)
pop ebp

这两条指令啥都没做,不过会影响静态分析。
下面这五条同样等效于nop,对应上面idc代码的第三种。

call    $+5
xchg    eax, ds:[esp]
lea     eax, [eax+0Ch]
xchg    eax, ds:[esp]
retn

下面这几条同样等效于nop,对应上面idc代码的第一种。这里需要注意,jmp 常数是相对于jmp指令尾部而言的。下面的ret和int 3会被直接跳过。
EB是short jmp,后面操作数只有一字节。EB 03 xx xx xx中无论xx是什么,都会被跳过。
E9是near jmp,后面操作数为两字节。
EA是far jmp,后面操作数为四字节。

short jmp 3
ret
int 3

伪代码中如果出现以下代码,可能也是nop:

interlockedExchange(a,b) 能以原子操作的方式交换俩个参数a, b,并返回a以前的值。
__writeeflags()        将指定的值写入程序状态和控件 (EFLAGS) 寄存器。就是pushf。
__readeflags()           读取程序状态和控件 (EFLAGS) 寄存器。就是popf。

其它patch时常见的花指令

jz和jnz同一个地方;
E8被识别为call;
[addr处] jmp addr+1;

双进程保护

这里不是指“防止关闭”。这里指的是软件作者自己写了一个调试器“占坑”,用父进程调试子进程,以阻止破解者调试、并利用异常处理的路径分叉(调试进程和被调试进程都可能是处理者)来增加跟踪难度的行为。“双进程保护”这个名字来自《加密与解密》。
这类题的标志性特征就是createprocess并使用了DEBUG_ONLY_THIS_PROCESS
(0x00000002)或者DEBUG_PROCESS(0x00000001)的creation flag。代码的结构可以分为“简易调试器”和“被调试代码”两部分。可以先搜索一下“windows简易调试器的实现”,能获取一些必要的背景知识。
解决的思路仍然是用nop和jmp回避整块简易调试器的代码(不能让这个调试器启动起来,否则就无法动调),但不止于此。因为调试进程并不是什么都没做的,调试进程会处理异常。出题人会故意在汇编中制造一些异常,比如:

  • 0xC0000094 Integer division by zero
  • 0xc000001d Illegal Instruction

对于前者,一种处理异常的方法是EIP+=2(div指令长度为2,也就是直接下一条的意思)。
对于后者,也可以写出类似的异常处理(例题中为eip+=3)。
由于出题人的调试器会妥善处理这些异常,所以直接运行时不会有问题。这就导致了一个两难局面:不去掉出题人的调试器,无法动调;去掉出题人的调试器,无法F9。
如果去掉出题人的调试器后直接拿自己的调试器F9,会不断停在出题人设置的异常(比如int 3和div)上,需要你经常set ip、反复去patch。
如果想让题目更难的话,可以用更复杂的异常处理方式(而不只是eip增),也可以在父进程(调试进程)中增加更复杂的、有意义的内容,以增加直接nop掉的成本(破解者需要模拟执行这些内容后,才能毫无顾虑地nop)。

mfc

如果有输入框,通过resource hacker查找输入框的id(所得id为10进制),在ida中搜索对应十六进制id,就能找到getText,从而找到check函数等关键位置。
如果有按钮,xspy对button按钮进行检测,检测出id之后,对整个MFC窗口进行检测,就能用id查到点击按钮后触发的函数(下图的onCommand)。
在这里插入图片描述
如果没有提供上述交互(输入框、按钮),看看有没有自定义消息(如下图)。可以自己写代码来发送这个msg来进行交互。
在这里插入图片描述

// 1.cpp : 定义控制台应用程序的入口点。
//注意是VS的MFC运行。所有的MFC 的.cpp文件第一条语句都是#include“stdafx.h”.

#include "stdafx.h"
#include<stdio.h>
#include<string.h>
#include "windows.h"

int main()
{
	HWND h = FindWindowA("944c8d100f82f0c18b682f63e4dbaa207a2f1e72581c2f1b",NULL);
	//HWND h = FindWindowA(NULL, "Flag就在控件里");
	//HWND h = FindWindowA("944c8d100f82f0c18b682f63e4dbaa207a2f1e72581c2f1b", "Flag就在控件里");
	//这里用到两个关键函数,一个是获取窗口句柄函数,第二个就是根据句柄发送消息函数。获取句柄的FindWindowA中第一个可以传入类名,第二个可以传入标题,因为我们两个都有,所以任意一个都可以锁定程序窗口。
	if (h)
	{
		SendMessage(h, 0x464, NULL, NULL);
		//发送函数中第二个是区别其他消息的常量值,这里题目用了自定义常量值,所以我们要对应一致。
	}
	getchar();
	return 0;
}

tea模板

特征就是移位、两部分互相运算。


from libnum import *

l = [2936232810,479881757,1187579365,1870219775]
keys = [2232106884, 443933925, 887867854, 2475959571, 656951854, 2429565456, 564163628, 1528392103, 3056784222, 3676191895, 3057416514, 3711600247, 3128233222, 3382368592, 2469769916, 868161824, 1736323680, 2744845574, 1194723888, 2480028295, 665089334, 2885264336, 1475561420, 1027060899, 2054121846, 3361673682, 2428380120, 2845300551, 1395633862, 846084946, 1692169952, 272236806, 544473676, 425754791, 851509650, 439900147, 879800366, 2024180243, 4048360562, 3369892084, 2444816952, 3765763143, 3236559074, 858681714, 1717363516, 1683076390, 3366152872, 3820967107]
mask = 0xffffffff
def rol(a, b):
  return ((a << b) & mask) | (a >> (32-b) )

def ror(a, b):
  return ((a << (32-b) ) & mask) | (a >> b)

def dec(a, b):
  aa = a
  bb = b
  for i in range(24):
    bb += 0x100000000
    bb -= (rol(aa, 19) + keys[47-i*2] ) ^ rol(aa, 7)
    bb &= 0xffffffff
    aa += 0x100000000
    aa -= (rol(bb, 7) + keys[47-i*2-1] ) ^ rol(bb, 19)
    aa &= 0xffffffff
  return n2s(aa)[::-1] + n2s(bb)[::-1]
flag = b''
for i in range(0, len(l), 2):
  flag += dec(l[i], l[i+1] )
print('flag{' + flag.hex() + '}')

rc4模板

rc4特征就是box[(box[x] + box[y]) % 256]),非常有辨识度。
下面代码对应的题目是这样的,获取系统分钟和秒钟作为密钥,所以解题时穷举3600次密钥即可。
如果题目更简单一些,密钥大概率就是个常量字符串了。


from hashlib import sha256
def rc4(data, key):
  x = 0
  box = list(range(256))
  for i in range(256):
    x = (x + box[i] + (key[i % len(key)])) % 256
    box[i], box[x] = box[x], box[i]
  x = y = 0
  out = []
  for char in data:
    x = (x + 1) % 256
    y = (y + box[x]) % 256
    box[x], box[y] = box[y], box[x]
    out.append(chr((char) ^ box[(box[x] + box[y]) % 256]))

  return ''.join(out)
enc = open('flag.txt.enc', 'rb').read()
for i in range(60*60):
  k = sha256(str(i).encode()).digest()
  d = rc4(enc, k)
  if 'flag{' in d:
    print(d, i)

文件patch把代码写到哪

有人说,401000,直接写在text段开始。
对于linux elf,常见于awd的patch,可以写在eh_frame段(似乎gcc编译就会有这个段)。

附录

python循环移位

def ror8(inte, bit):
    if inte != inte & 0xff:
        print('input warning')
        inte = inte & 0xff
    part1 = inte >> bit
    part2 = (inte << (8-bit)) & 0xff
    return (part1 | part2) & 0xff

黑盒穷举

import subprocess

binary = '/home/rookie19/Desktop/mx'
ctr = 0

for ch1 in range(20, 128):
	# for ch2 in range(20, 128):
		# cand = 'flag{' + chr(ch1) + chr(ch2)
	cand = 'flag' + chr(ch1)

	obj = subprocess.Popen(["qemu-mips", binary], stdin=subprocess.PIPE, stdout=subprocess.PIPE)

	obj.stdin.write(str.encode(cand + '\n'))
	# obj.stdin.flush()
	obj.stdin.close()

	response = obj.stdout.readline()
	obj.stdout.close()

	response = response.decode()
	# print(response)
	# ctr += 1
	# if ctr % 100 == 0:
	# 	print(response)
	# if response[0] == '│':
	# 	print(cand)
	# 	exit(0)

2023 ciscn感想

题目形式很新。可信计算(cry)、量子通信(cry)、目标检测对抗样本生成(misc)。逆向有一道berkley snap少儿编程。
ctf常常需要现场学习的能力。比如逆向出一道小众语言;或者像这次的crypto一样,附件里塞一个很长的讲BB84的word文档;抑或是awd现场搜特定版本cms的漏洞;或者像这次的misc一样,现场搜目标检测对抗样本论文。
ctf也需要灵活的头脑。比如给了shell的题目有时有非预期解;利用好flag格式有时可以直接穷举;awd中可以偷窃别人的攻击流量进行重放。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/658689.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

我的创作纪念日——512

机缘 没想到不知不觉在CSDN创作就512天了&#xff0c;想到一开始就仅仅想在CSDN记笔记&#xff0c;到现在成为一个小博主&#xff0c;认识到了很多志同道合的伙伴&#xff0c;中间创作我也曾经懒惰过&#xff0c;放弃过&#xff0c;但我一次又一次重新进行创作&#xff0c;虽然…

AcWing801: 二进制中1的个数(两种方法详解)

原题引出 方法一&#xff1a;使用lowbit 算法的时间复杂度为 O ( n l o g n ) O(nlogn) O(nlogn)&#xff0c;使用lowbit操作&#xff0c;每次操作截取一个数字的最后一个1后面的所有位&#xff0c;每次减去lowbit得到的数字&#xff0c;直到数字减到0&#xff0c;就得到了最终…

【MySQL】选择专题(七)

文章目录 选择题选择题 在关系R ( R # , RN , S # )和S ( S # , SN , SD )中, R 的主码是R # , S 的主码是S #,则S#在R 中称为( A )。 A 外码 B 候选码 C 主码 D 超码 设关系R和S的属性个数分别为2和3,那么等价于( B )。 A. σ1<2(RS) B. σ1<4(RS) C. σ1<2(R…

我们世界中的计算机——从大师视角诠释计算常识

计算机和通信系统&#xff0c;以及由它们所实现的许多事物遍布我们周围。其中一些在日常生活中随处可见&#xff0c;比如笔记本电脑、手机和互联网。今天&#xff0c;在任何公共场所&#xff0c;都会看到许多人在使用手机查询交通路线、购物以及和朋友聊天。与此同时&#xff0…

【大数据】大数据相关概念

文章目录 大数据&#xff1a;一种规模大到在获取、存储、管理、分析方面大大超出了传统数据库软件工具能力范围的数据集合&#xff0c;具有海量的数据规模、快速的数据流转、多样的数据类型以及价值密度四大特征。Hadoop&#xff1a;是一个能够对大量数据进行分布式处理的软件框…

15-3.自定义组件的生命周期函数

目录 1 组件自身的生命周期函数 1.1 使用lifetimes声明生命周期函数 1.2 不使用lifetimes声明生命周期函数 2 组件所在页面的生命周期函数 1 组件自身的生命周期函数 created 组件实例刚刚被创建后执行&#xff0c;可以理解为 html模板刚刚搞好attached 组件被放入节…

万物的算法日记|第六天

笔者自述&#xff1a; 一直有一个声音也一直能听到身边的大佬经常说&#xff0c;要把算法学习搞好&#xff0c;一定要重视平时的算法学习&#xff0c;虽然每天也在学算法&#xff0c;但是感觉自己一直在假装努力表面功夫骗了自己&#xff0c;没有规划好自己的算法学习和总结&am…

DJ4-2 数据报网络和虚电路网络

目录 一、连接和无连接服务 二、数据报网络 1、数据报网络的转发表 2、数据报网络的特点 三、虚电路网络 (Virtual Circuits)* 1、虚电路网络的工作方式 2、虚电路网络的特点 一、连接和无连接服务 任何网络中的网络层只会提供两种服务之一&#xff0c;不会同时提供 数…

Mysql数据库之事务(山高水远,他日江湖再见)

文章目录 一、事务的概念二、事务的ACID特点1.原子性&#xff08;Atomicity&#xff09;2.一致性&#xff08;Consistency&#xff09;3.隔离性&#xff08;lsolation&#xff09;4.持久性&#xff08;Durability) 三、并发访问表的一致性问题和事务的隔离级别1.并发访问表的一…

融合模型stacking14条经验总结和5个成功案例(互联网最全,硬核收藏)_机器学习_人工智能_模型竞赛_论文参考

我看了很多关于融合模型stacking文章&#xff0c;很多作者倾向于赞美融合模型stacking&#xff0c;对其缺点轻描淡写&#xff0c;这容易误导初学者。一叶障目就是这意思。 我的很多学员喜欢用融合模型作为论文或专利创新点&#xff0c;这是一个热门技术。 最近有个同学在论文…

设计模式之单例模式笔记

设计模式之单例模式笔记 说明Singleton(单例)目录单例模式之饿汉式-静态成员变量写法测试类 单例模式之饿汉式-静态代码块写法测试类 单例模式之懒汉式-线程不安全写法和线程安全写法测试类 单例模式之懒汉式-双重检查锁方式(推荐使用的方式)单例模式之懒汉式-静态内部类方式(推…

Mysql数据库之存储引擎(羡慕她人,不如提升自己)

一、存储引擎概念 MySQL中的数据用各种不同的技术存储在文件中&#xff0c;每一种技术都使用不同的存储机制、索引技巧、锁定水平并最终提供不同的功能和能力&#xff0c;这些不同的技术以及配套的功能在MySQL中称为存储引擎。 存储引擎是MySQL将数据存储在文件系统中的存储方…

ELK日志收集系统简述

一、概述 &#xff08;一&#xff09;ELK由三个组件构成 ELK是三个开源软件的缩写&#xff0c;分别是Elasticsearch、Logstash、Kibana ELK 架构基本组成 &#xff08;二&#xff09;作用 1、日志收集 2、日志分析 3、日志可视化 &#xff08;三&#xff09;为什么使用EL…

计网之应用层

因特网协议概述 常用协议应用层HTTP&#xff08;超文本传输协议&#xff09;、FTP&#xff08;文件传输协议&#xff09;、SMTP&#xff08;简单邮件传输协议&#xff09;、DNS&#xff08;域名系统&#xff09;、DHCP&#xff08;动态主机配置协议&#xff09;、SNMP&#xff…

15-6.自定义组件的代码共享

在微信小程序中使用 behaviors 进行代码共享&#xff0c;功能类似于vue的mixins 每个behavior可以包含一组属性、数据、生命周期函数和方法 每个组件可以引用多个behavior&#xff0c;behavior也可以引用其他的behavior 目录 1 创建behavior 2 使用behavior 3 behavio…

机器学习融合模型stacking14条经验总结和5个成功案例(互联网最全,硬核收藏)

我看了很多关于融合模型stacking文章&#xff0c;很多作者倾向于赞美融合模型stacking&#xff0c;对其缺点轻描淡写&#xff0c;这容易误导初学者。一叶障目就是这意思。 我的很多学员喜欢用融合模型作为论文或专利创新点&#xff0c;这是一个热门技术。 最近有个同学在论文…

MySQL:七种 SQL JOINS 的实现(图文详解)

MySQL&#xff1a;7种SQL JOINS的实现 前言一、图示表示二、代码举例1、INNER JOIN&#xff08;内连接&#xff09;2、LEFT JOIN&#xff08;左连接&#xff09;3、RIGHT JOIN&#xff08;右连接&#xff09;4、OUTER JOIN&#xff08;全连接&#xff09;5、LEFT EXCLUDING JOI…

微信小程序入门学习02-TDesign中的自定义组件

目录 1 显示文本2 自定义组件3 变量定义4 值绑定总结 我们上一篇讲解了TDesign模板的基本用法&#xff0c;如何开始阅读模板。本篇我们讲解一下自定义组件的用法。 1 显示文本 官方模板在顶部除了显示图片外&#xff0c;还显示了一段文字介绍。文字是嵌套在容器组件里&#xf…

数据库的操作

前言 在之前的文章中&#xff0c;我们已经了解了什么是数据库&#xff0c;以及为什么有数据库&#xff0c;和数据库有什么作用&#xff0c;有了这些宏观概念之后&#xff0c;本章为大家进一步详细介绍对于数据库在Linux上如何具体操作。 1.创建数据库 1.1创建数据库语法 语法…

读书:《敏捷软件开发工具----精益开发方法》

《敏捷软件开发工具----精益开发方法》&#xff08;Lean Software Development: An Agile Toolkit&#xff09;由Mary Poppendieck和Tom Poppendieck合著&#xff0c;2003年出版&#xff0c;尽管已经有20个年头了&#xff0c;但书中的理念和方法仍然具有很高的实践价值&#xf…