2020.04.27-2020.05.03

Windows内核基础

内核的数据结构

TEB

TEB结构(Thread environment block,线程环境块)和PEB一样,是应用层中的结构。
包含了系统频繁使用的一些与线程相关的数据,进程中每个线程(除系统线程)都有一个自己的TEB,一个进程的所有TEB都存放在从0x7FFDE000开始的线性内存中,每4KB为一个完整的TEB
用WinDbg的本地调试功能可以查看系统中的TEB结构

TEB访问

可以通过NtCurrentTab函数调用和FS段寄存器访问两种方式访问TEB结构

  1. NtCurrentTab
    一个ntdll.dll中的函数,该函数可以返回当前线程TEB的地址
  2. FS段寄存器
    当代码运行在r3时,fs指向的段的基地址即为当前线程的TEB

PEB

PEB(Process Environment Block,进程环境块)存在于用户地址空间中,每个进程都有自己的PEB信息
PEB结构的地址放在TEB中,因此可以通过fs:[偏移量]访问PEB的地址

使用OD从零开始Cracking

汇编指令

  1. nop
  2. 堆栈相关指令
    1. push
      push[内存地址]
      push[eax]
      push 数值
    • ptr:防止两个操作数不一样。
      用byte/word/dword ptr指定内存单元的长度(字节、字、双字)
    1. pop
    2. pushad
      按照eax、ecx、edx、ebx、esp、ebp、esi、edi的顺序把所有通用寄存器压入栈
    3. popad
      把pushad入栈的值取出(顺序相反)
    4. 16位程序中有pusha、popa
  3. 赋值指令
    1. mov
    2. movsx(操作有符号数)
      第一个操作数的位数比第二个操作数多,第二个填充第一个的前面几位
      填充的结果跟填充数字正负有关。用负数填充,结果的剩余部分填F;整数填充剩余部分填0。
      如:用F000填EAX,结果为FFFFF000;用1234填EAX,结果为00001234.
      (16位数的正数范围为0~7FFF,负数范围为8000~FFFF)
    3. movzx(操作无符号数)
      与movsx相似,但剩余部分总填充0
    4. LEA
      取地址指令,第一个操作数是通用寄存器,第二个是内存单元的地址(而不是值)
      如"LEA EAX,DOWRD PTR DS:[ECX+38]"不是获取内存中[ECX+38],而要计算ECX+38的值,并赋给EAX
    5. XCHG
      交换两个操作数的值,寄存器/内存单元和寄存器

数学指令

  1. inc dec
  2. add sub
  3. adc (带进位的加法)
    将两个操作数和进位标志(CF)的值相加放到第一个操作数中
  4. SBB
    计算(第一个操作数-第二个操作数)再减去进位标志,将结果 存到第一个操作数中
  5. MUL
    无符号数乘法。只有一个操作数,操作数和EAX相乘,结果放到EDX:EAX中
  6. IMUL
    用于有符号数的乘法
    一个操作数时类似于MUL。
    当有两个操作数时,两者相乘,结果放到第一个操作数中
    当有三个操作数时,如,“IMUL EBP,DWORD PTR [ESI+74], FF800002”,意思是EBP=[ESI+74]*FF800002
  7. DIV(无符号)/IDIV(有符号)
    DIV只有一个操作数,结果存放到EDX:EAX中
    IDIV:
    一个操作数时,于DIV相似
    两个操作数时,第一个除以第二个,结果存放到第一个操作数中
    三个操作数时,第二哥除以第一个,结果存放到第一个操作数中
    (与IMUL类似)
  8. XADD(交换并相加)
    XCHG和ADD的组合,先将两个操作数交换数值,然后值相加赋给第一个操作数
  9. NEG
    取反

逻辑指令

两个操作数,将两个操作数按位运算,并将结果存入第一个操作数中

  1. AND
    两个二进制位都为1,结果为1,此外都为0
  2. OR
    有一位为1,结果就为1
  3. XOR
    不同取1,相同取0
  4. NOT
    取反(1-0,0-1)

两个攻防世界上的新手re题

其实没看出来哪跟re有关了

第一个

https://adworld.xctf.org.cn/task/answer?type=reverse&number=4&grade=0&id=5076&page=1

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
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[]) {
if (argc != 4) {
printf("what?\n");
exit(1);
}
unsigned int first = atoi(argv[1]);
if (first != 0xcafe) {
printf("you are wrong, sorry.\n");
exit(2);
}
unsigned int second = atoi(argv[2]);
if (second % 5 == 3 || second % 17 != 8) {
printf("ha, you won't get it!\n");
exit(3);
}
if (strcmp("h4cky0u", argv[3])) {
printf("so close, dude!\n");
exit(4);
}
printf("Brr wrrr grr\n");
unsigned int hash = first * 31337 + (second % 17) * 11 + strlen(argv[3]) - 1615810207;
printf("Get your key: ");
printf("%x\n", hash);
return 0;
}

flag就是解出的hash值,没啥难度。(就是为了凑行数)

第二个

https://adworld.xctf.org.cn/task/answer?type=reverse&number=4&grade=0&id=5077&page=1

就用16进制编辑器打开然后搜索“flag”

写了个爬自己网易云红心歌单的爬虫

一个爬取自己网易云歌单的爬虫

其实还没写完