winxp
windbg
xp中安装vc6(网上找的绿色版,安装包才几十mb,适用于做实验)
段描述符
代码和数据段
s位为1是代码和数据段描述符
type值小于8为数据段,大于等于8为代码段
系统段
s位为0是系统段描述符
我们需要构造一张tss,所以type的值应该为hex:b;bin:1011
当前3张图为主要用到的东西
通过 call fat 来实现进入1环,主要需要在gdt中构造3个段描述符:
1环的cs,1环的ss和一块tss
先查看gdt,我们需要构建3个描述符,所以需要3个空白处
这是海哥原视频中的构建1环tss内存的代码,拿出来改改
我们需要替换到其中的段寄存器:
可以看看,无论cs,还是ss,都指向一个0环的段中,我们去gdt中找找
通过cs和ss拆解得到index,找到这两个描述符,直接拖出来改改就行。
我们代码中的tss内存首地址为:0x12fdcc
填入我们刚刚查找出来的三个空描述符中的随便一个
index:dec:12 段选择子selector:bin:1001 0001;hex:91
8003f090 eq 8003f090 0000e912`fdcc0068
index:dec:19 1001 1001 selector: 99 hex
8003f098 eq 8003f098 00cfb900`0000ffff
index:dec:21 1010 1001 selector: a9 hex
8003f0a8 eq 8003f0a8 00cfb300`0000ffff
好了,段描述符已经准备就绪
通过 !process 0 0 来获取进程信息
从windbg中找到我们已经运行的进程
cr3是用来切换进程,找到这个值,填入到VMware中的进程窗口中
然后下一步,运行
从当前cs和ss的cpl我们就可以看出,我们成功进入1环,并且执行了我们的代码。
由于我们的 call 是一个任务切换,所以并不会向堆栈中压入ss、esp、cs、返回地址,所以返回时要从 tss 中的 ptl 拿取返回值,这时我们要指定 eflags 的 nt 为1,这样 iretd 才不会从堆栈中取返回值。
我们将刚刚我们自己写入gdt的段描述对应的段选择子,写入tss中,tss是一块内存,我们可以直接写入,然后会在我们call时,进行任务切换,替换我们设定好的寄存器值
好了,完毕,暂时不能在1环中使用 int 3中断,后续搞明白了我再回来补上。
来自一枚菜鸡的总结
DWORD iTss[
0x68
]
=
{
0x00000000
,
/
/
link
0x00000000
,
/
/
esp0
0x10000010
,
/
/
ss0
0x00000000
,
/
/
esp1
0x00000000
,
/
/
ss1
0x00000000
,
/
/
esp2
0x00000000
,
/
/
ss2
(DWORD)iCr3,
/
/
cr3
0x00401020
,
/
/
eip
0x00000000
,
/
/
eflags
0x00000000
,
/
/
eax
0x00000000
,
/
/
ecx
0x00000000
,
/
/
edx
0x00000000
,
/
/
ebx
(DWROD)bu,
/
/
esp
0x00000000
,
/
/
ebp
0x00000000
,
/
/
esi
0x00000000
,
/
/
edi
0x00000023
,
/
/
es
0x00000008
,
/
/
cs
0x00000010
,
/
/
ss
0x00000023
,
/
/
ds
0x00000030
,
/
/
fs
0x00000000
,
/
/
gs
0x00000000
,
/
/
ldt
0x20ac0000
};
DWORD iTss[
0x68
]
=
{
0x00000000
,
/
/
link
0x00000000
,
/
/
esp0
0x10000010
,
/
/
ss0
0x00000000
,
/
/
esp1
0x00000000
,
/
/
ss1
0x00000000
,
/
/
esp2
0x00000000
,
/
/
ss2
(DWORD)iCr3,
/
/
cr3
0x00401020
,
/
/
eip
0x00000000
,
/
/
eflags
0x00000000
,
/
/
eax
0x00000000
,
/
/
ecx
0x00000000
,
/
/
edx
0x00000000
,
/
/
ebx
(DWROD)bu,
/
/
esp
0x00000000
,
/
/
ebp
0x00000000
,
/
/
esi
0x00000000
,
/
/
edi
0x00000023
,
/
/
es
0x00000008
,
/
/
cs
0x00000010
,
/
/
ss
0x00000023
,
/
/
ds
0x00000030
,
/
/
fs
0x00000000
,
/
/
gs
0x00000000
,
/
/
ldt
0x20ac0000
};
DWORD dwOK;
DWORD dwESP;
DWORD dwCS;
DWORD dwEFLG;
DWORD dwSS;
void __declspec(naked) Func()
{
dwOK
=
1
;
__asm
{
/
/
int
3
/
/
实验会发现当前eip的eflgs中的nt位为
1
,看截图
/
/
返回地址从tss中的ptl中拿出
/
/
PTL为自动填补的上一个tss连接
push eax
pushfd
pop eax
mov dwEFLG,eax
or
eax,
0x4000
push eax
popfd
mov eax,
0
mov dwESP,esp
mov ax,ss
mov dwSS,eax
mov ax,cs
mov dwCS,eax
pop eax
iretd
}
}
/
/
过去当前eip,通过函数调用堆栈中的返回地址获取
void __declspec(naked) GetEIP()
{
__asm
{
mov eax,dword ptr ss:[esp]
ret
}
}
int
main()
{
/
/
查看函数地址
printf(
"Function addr:[%x]\n"
, &Func);
char bu[
0x10
];
/
/
12ff70
int
iCr3;
printf(
"input CR:\n"
);
scanf(
"%x"
,&iCr3);
/
/
通过windbg工具, !process
0
0
指令获取
/
/
写入寄存器的值,我们刚刚设定好的段选择子
DWORD ITss[
0x68
]
=
{
0x00000000
,
/
/
link
0x00000000
,
/
/
esp0
0x00000000
,
/
/
ss0
0x00000000
,
/
/
esp1
0x000000a9
,
/
/
ss1
0x00000000
,
/
/
esp2
0x00000000
,
/
/
ss2
(DWORD)iCr3,
(DWORD)&Func,
/
/
eip
0x00000000
,
/
/
eflags
0x00000000
,
/
/
eax
0x00000000
,
/
/
ecx
0x00000000
,
/
/
edx
0x00000000
,
/
/
ebx
(DWORD)bu,
/
/
esp
0x00000000
,
/
/
ebp
0x00000000
,
/
/
esi
0x00000000
,
/
/
edi
0x00000023
,
/
/
es
0x00000099
,
/
/
cs
0x000000a9
,
/
/
ss
0x00000023
,
/
/
ds
0x000000a9
,
/
/
fs 这里不管改不改都能跑,问题不大
0x00000000
,
/
/
gs
0x00000000
,
/
/
ldt
0x20ac0000
};
printf(
"tss adress:[%x]\n"
, &ITss);
system(
"pause"
);
char buff[
6
];
*
(DWORD
*
)&buff[
4
]
=
0x91
;
__asm
{
call fword ptr[buff]
}
/
/
查看当前的 eip
DWORD eipp;
GetEIP();
__asm
{
mov eipp,eax
}
/
/
打印输出值
printf(
"current eip:%x\n"
, eipp);
printf(
"TSS:[%x]\n"
,(DWORD)(ITss[
0
]));
printf(
"ESP = %x CS = %x SS = %x Eflgs = %x\n"
, dwESP,dwCS,dwSS,dwEFLG);
if
(dwOK
=
=
1
)
{
printf(
"Ring1 success!\n"
);
}
else
{
printf(
"Ring1 failed!\n"
);
}
system(
"pause"
);
return
0
;
}
DWORD dwOK;
DWORD dwESP;
DWORD dwCS;
DWORD dwEFLG;
DWORD dwSS;
void __declspec(naked) Func()
{
dwOK
=
1
;
__asm
{
/
/
int
3
/
/
实验会发现当前eip的eflgs中的nt位为
1
,看截图
/
/
返回地址从tss中的ptl中拿出
/
/
PTL为自动填补的上一个tss连接
push eax
pushfd
pop eax
mov dwEFLG,eax
or
eax,
0x4000
push eax
popfd
mov eax,
0
mov dwESP,esp
mov ax,ss
mov dwSS,eax
mov ax,cs
mov dwCS,eax
pop eax
iretd
}
}
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)