ExpressCache OEM Patch v2.0

按照zts9989同学的提示再次进行分析,果然发现1.3.110以上版本存在文件校验的暗桩,故更换破解方式。

此次补丁使用了特征码定位,所以理论上可以兼容多个版本,但是能兼容多少我也不知道。个人环境win10x64 118版本、win7x64 86版本测试通过。别的版本也欢迎各位观众帮忙测试,如有问题可在下面讨论。

用法:停止ExpressCache服务后应用此补丁。

下载地址:ECPatch.7z,解压密码仍然为本站域名。

Known issues:
1、win7 x64只能装110版本。这是因为win7及以前的系统只认sha1签名,而之后的系统都是sha256签名。据说打KB3033929补丁就可以支持sha256了。
2、关机掉缓存重启不掉。可能是硬件坑,见楼下z同学的研究历程。

西数硬盘调整APM避免停转

跟daddy置换电脑时购买了西数WD10JPVX笔记本硬盘作为移动硬盘,结果该硬盘有个坑爹的设定,就是每当空闲十几秒就直接停转了,再次启动时系统就会卡个两秒钟。可能西数没去考虑将此硬盘作为从盘或移动硬盘使用。

搜索到了“C1门”,试着用wdidle3修改,表示对C1(磁头归位)也许有效,但对停转(04)没有效果。

继续搜索得知这是APM(高级电源管理)的问题,此型号APM默认值为0x60,比较流行的解决方法是安装CrystalDiskInfo,将APM关闭或者设为0x80。但由于硬盘断电后该设置会复位,所以需要将CrystalDiskInfo设为开机启动。

为了一个破硬盘要装个daemon?po主表示不能忍,再说我这是移动硬盘,插别的电脑上怎么办,中国能移动daemon又移不动。

考虑研究一下如何调用APM,然后自己写一个小程序放到移动硬盘上,插上后运行一下。

期间参考了这篇文章,但是编译后发现只能支持本地硬盘,无法识别移动硬盘。谷歌未果,只好OD挂一下CrystalDiskInfo,发现其对本地硬盘和移动硬盘调整APM时DeviceIoControl的ioctl id不一样,搜索此id得知USB移动硬盘是SCSI接口。继续搜索得到关于SCSI ATA PASSTHROUGH调用的白皮书,经多次试验成功实现修改APM。

代码如下:

#include <Windows.h>
#include <ntddscsi.h>
#include <stdio.h>

void main()
{
	char name[260] = "\\\\.\\";
	GetModuleFileNameA(NULL, &name[4], 256);
	name[6] = 0;
	HANDLE handle = CreateFileA(name, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
	STORAGE_DEVICE_NUMBER sdn;
	DWORD nRet = 0;
	BOOL ret = DeviceIoControl(handle, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &sdn, sizeof(sdn), &nRet, NULL);
	sprintf(&name[4], "PhysicalDrive%d", sdn.DeviceNumber);
	CloseHandle(handle);
	handle = CreateFileA(name, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
	ATA_PASS_THROUGH_EX aptex = {0};
	aptex.Length = sizeof(ATA_PASS_THROUGH_EX);
	aptex.TimeOutValue = 2;
	aptex.CurrentTaskFile[6] = 0xEF;
	aptex.CurrentTaskFile[0] = 0x05;
	aptex.CurrentTaskFile[1] = 0x80;
	ret = DeviceIoControl(handle, IOCTL_ATA_PASS_THROUGH, &aptex, sizeof(ATA_PASS_THROUGH_EX), NULL, 0, &nRet, NULL);
	SCSI_PASS_THROUGH spt = {0};
	spt.Length = sizeof(SCSI_PASS_THROUGH);
	spt.TimeOutValue = 2;
	spt.CdbLength = 12;
	spt.Cdb[0] = 0xA1;
	spt.Cdb[1] = 3 << 1;
	memcpy(&spt.Cdb[3], aptex.CurrentTaskFile, 8);
	ret = DeviceIoControl(handle, IOCTL_SCSI_PASS_THROUGH, &spt, sizeof(SCSI_PASS_THROUGH), NULL, 0, &nRet, NULL);
	CloseHandle(handle);
}

程序会根据自己所在的盘符打开PhysicalDrive,并尝试SATA与SCSI两种方式修改APM值为0x80。

对于不想编译的同学,也可直接点此下载,解压密码为本站域名。不要修改文件名,windows会将文件名带有Setup的程序以UAC管理员权限启动。

小工具:Everybackup

五年前的这个时候(2010年12月7号),某人本着天下无贼的思想把电脑带去了演出礼堂,用实际行动证明了天下无贼是不成立的(那个时候世界上还没有nozuonodie这个词)。损失包括并不仅限于一年的和某人的聊天记录,导致这段时间由于后来的强行删除记忆而永远成了断片;以及正在开发的约万行LibCHD及相关项目,导致本人月流水万元的游戏辅助工作室直接倒闭。

在此之后,关于如何备份代码(或者别的重要文件)的问题一直很困扰,直接打包会有一堆无用的文件(比如Debug/Release目录、IntelliSense数据库),浪费时间和空间。

后来发现WinRAR、7zip可以写通配符的文件列表,如*.cpp *.vb这样,也可以写排除列表,例如*\Debug\*,这样用了一段时间,发现了个问题——有些我fork下来编译的类库我并不需要备份,因为这些不是『我的』代码。

好吧,rar和7z都可以写排除列表。可是排除列表只有一个,而这种项目有时藏得很深。最好是能有一个能在每目录里建个配置文件什么的来说明这个目录下哪些需要备份哪些需要排除,类似apache的.htaccess。这个并不复杂,想了下就用批处理写了个枚举每个目录下的include和exclude文件然后汇总成全的include和exclude交给winrar。

这样又用了一段时间,又发现两个问题。第一,假如父目录默认排除了*.exe,而某个子目录需要包含*.exe(例如一个做pediy的项目),那么实测子目录的包含不能生效。第二,winrar对目录的扫描会花费很多时间。

第一个问题是集合运算的逻辑题,严格按照父目录——子目录的顺序求并集(包含)和差集(排除)即可解决。第二个问题,想到咱做程序的必备Everything搜索,用Everything索引好的列表想必应该很快。

于是研究了一下写出此工具。用法很简单,在任意需要备份的目录中建立列表文件backup.lst,写上需要包含和排除的文件名或通配符。软件会调用everything找出全盘所有的backup.lst,然后再根据里面的通配符再次调用everything找到符合要求的文件。并利用.NET 3.5 LINQ的集合运算最终生成备份文件列表喂给winrar。

由于everything的专业性,建表速度比winrar自己扫描要快很多。目前的代码筛选我的Projects目录各种文件类型只要4秒,而winrar自己的方案要10秒以上。主要瓶颈似乎是与everything主窗口IPC通信,如果改成异步并行可能会更快。

目前测试正常。代码和release目前都在github上,欢迎试用或改造。https://github.com/gmsj0001/Everybackup

 

ATL/WTL黑科技

1、真正的按需编译

一般来说我们提到“类库”概念的概念马上就想到DLL,也就是运行时类库。这样写框架的话框架有多少代码DLL就有多大。据实验最新的MFC的程序只需要一个空的对话框,静态编译出来EXE大小就有1M。

而C++模板技术几乎相当于宏替换,代码的实现都直接写在头文件里,并且只有在真正调用时才会编译。这样使得ATL对SDK的封装是在源代码级别的,相当于用到什么才去拉一段代码贴上去。没有MFC那样庞大的设计结构,耦合性很低,编译出的代码也就很精练了。

2、编译期多态

和上面类似,使用C++模板可以实现编译期间基类对子类成员随便直接访问,而无需通过运行时虚函数,这在通常的面向对象编程思想中是反人类的。例如以下代码:

template<class T>
class CWindow
{
public:
	void Create()
	{
		CreateWindow((T*)this->ClassName, ...)
	}
};

class MyWindow : public CWindow<MyWindow>
{
public:
	MyWindow() : ClassName("My Window Class")
	{
	}
	char* ClassName;
};

第一次看到这样的代码我觉得我就在想,卧槽面向对象不带这样搞的。。。

3、动态代码实现HWND映射到窗口类指针

很久以前我就在设计如何在C++中实现类成员函数的委托,这玩意最大的用处可能就是窗口子类化了,可以省去维护一个HWND到指针的映射表,后来就写了一个动态代码的方案将this指针填写到ECX中(lxf.me/217)。今天发现ATL在几十年前就用上这种方法了,并且实现得比我的更加优雅和类型安全,还顺便把x86、x64、ia64、arm、mips等众多构架的实现都写好了(有兴趣可阅读atlstdthunk.h)。

综上,微软大法好,*nix一生黑。

生日悖论与Hash需要位数

m个数字随机选取n次,各不相同的概率P=((m-1)/m)^(n*(n-1)/2)

m、n很大时取最高次项公式近似为P=((m-1)/m)^(n^2/2)

lim(m->+…)((m-1)/m)^m=1/e

有P=(1/e)^(n^2/2/m)

n=(log(1/e)(P)*2*m)^(1/2)

当P=0.5时,代入上式n=(1.386*m)^(1/2)=1.177*m^(1/2)

在生日悖论原题中,m=365,得n=22.49,即班上有23人时生日出现重复的概率就超过0.5了(虽然是近似计算,但这个误差已经很小了)。

选取hash的话,考虑简单用32数表示hash,看上去能表示的数字有40多亿,但从上式中可以看出,出现碰撞的概率其实是其能表示的数字开平方的级别,也就是数万条数据就可能出现碰撞,这是很可怕的。

为了使crc32不容易碰撞,我们取P=0.95,可求得n=20991。若要求更高取P=0.99,求得n=9291。

(鉴于博主的高中数学已经还给老师,高数又都喂狗了,windows的计算器没法对亿级别的数做指数运算所以没法用最开始的公式验证,所以上面的计算如有疏漏还请读者指正)

破解Win2003标准版IAS Radius服务器客户端IP数限制

Win2003的Internet Authentication Service(IAS)服务是基于Windows Server平台的自带RADIUS服务端,结合Active Directory用于VPN拨入、无线802.1x接入等非常方便。

IAS要求必须指定来源客户端IP地址,查询帮助知可以填写192.168.0.0/24这样的子网地址以实现IP段,但填写后提示只有企业版才支持此功能。

因为没钱买企业版(好吧,其实是某云提供的企业版2003只有64位版,博主的1G内存小主机没必要因为这一个功能去换64位而损失各种兼容性),考虑进行破解。因为是系统Network Service服务,不便于使用OD调试,故优先用IDA静态分析,不过微软的系统DLL都公开了PDB方便用户调试和研究,分析起来其实并不复杂,IDA中很快找到对GetVersionExW的调用,随后连蒙带猜搞清周围的逻辑。破解思路与方法如下:

1、注册表HKLM\SYSTEM\CurrentControlSet\Services\RemoteAccess\Policy键,LicenseType值改为2是企业版的标志。这样以后IAS控制台就可以输入子网IP而不提示上面的对话框。

2、以上步骤后服务运行时还是会打版本不符合的EventLog,说明运行时还有判断,通过研究发现需要爆破。如图所示,iassvcs.dll中这里对OSVERSIONINFOEX.wSuiteMask和0x2做位测试,表示是否是企业版(参阅https://msdn.microsoft.com/en-us/library/windows/desktop/ms724833(v=vs.85).aspx)。用winhex将这里的jz改为nop即可。

3、system32目录下的文件受Windows File Protection(WFP)保护,直接替换会被秒还原。需要先将dllcache以及windows安装目录下的相应文件都删除或改名。另外替换正在使用中的文件也是将原文件改名,粘贴新文件,重启进程。

以上破解完成后测试服务启动正常,在我的环境下WFP好像也没有网上说的那样弹窗提示系统文件被fxxk了。实测可以添加0.0.0.0/0这样的ip地址匹配任意ip。

PHP小轮子计划

因为“PHP是世界上最好的语言”,所以大凡尝试过用原生PHP写网页的同学都会被要裸写一堆重复代码恶心到,不想恶心稍微偷懒一点的话又会被黑客分分钟sql注入之类的。

用框架是个好的选择,然而意味着学习成本提高、语言灵活性降低、程序执行效率降低。比如我显然没必要做去学习Zend然后给工作室写一个简单的学生管理系统这样大炮打蚊子的事。轻量级的框架固然也有,比如CI我就很喜欢,但也有着把简单问题复杂化以及某些功能用着不顺手的问题。有能力让框架比原生更简单的我觉得只有微软帝国,比如COM和.NET,设计上几乎找不到缺点。

于是萌生自己造个框架的想法。这个框架应该具有以下的特点:

框架应该极度简洁(强迫症发作),最好1000行以内搞定,以至于它其实只是个类库,接近原生开发。
不为了面向对象而面向对象,好好做单身狗(PHP-CGI作为单进程模型,本质为过程式编程,有些东西硬要去封装也必然会搞成singleton)。
在该框架基础上写代码清爽。
MVC,只做小项目的话也至少做到VC。
有一个URI router。
输入安全检查。
DB接口与安全,有需求可以做sql语句生成,但active record估计用不上。
session与cache存储。

20151028 Edit:

目前项目的设计架子已经基本成型,代码开始提交到github上,欢迎围观。
https://github.com/gmsj0001/x-php

ELAN触控板改手写板实验

原理:逆向了ETDDeviceInformation.exe中取内核原始PS2数据并计算出多点触摸坐标的部分,然后使用Microsoft.Ink墨迹库来做文字识别。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Threading;

namespace InkTest
{
    class ETD
    {
        [DllImport("kernel32")]
        static extern bool DeviceIoControl(IntPtr hDevice, uint dwIoControlCode, byte[] lpInBuffer, uint nInBufferSize, byte[] lpOutBuffer, uint nOutBufferSize, out uint lpBytesReturned, IntPtr lpOverlapped);
        [DllImport("kernel32")]
        static extern IntPtr CreateFileA(string lpFileName, uint dwDesiredAccess, uint dwShareMode, IntPtr lpSecurityAttributes, uint dwCreationDisposition, uint dwFlagsAndAttributes, IntPtr hTemplateFile);
        [DllImport("kernel32")]
        static extern IntPtr OpenEventA(uint dwDesiredAccess, bool bInheritHandle, string lpName);
        [DllImport("kernel32")]
        static extern bool ResetEvent(IntPtr hEvent);
        [DllImport("kernel32")]
        static extern uint WaitForSingleObject(IntPtr hHandle, int dwMilliseconds);

        static public void Init()
        {
            var t = new Thread(ETDThread);
            t.Start();
        }
        static public int X;
        static public int Y;

        static void ETDThread()
        {
            IntPtr hDevice = CreateFileA(@"\\.\ETD", 0xC0000000, 0, IntPtr.Zero, 3, 0, IntPtr.Zero);
            IntPtr hEvent = OpenEventA(0x1f0003, false, @"Global\ETDOther_GetKernelData");            
            byte[] ioctlBuf = new byte[124814];
            uint nRet = (uint)ioctlBuf.Length;
            Array.Copy(BitConverter.GetBytes((short)0x608), ioctlBuf, 2);
            DeviceIoControl(hDevice, 0x9c412000, ioctlBuf, nRet, ioctlBuf, nRet, out nRet, IntPtr.Zero);
            int bufIndex = BitConverter.ToInt32(ioctlBuf, 0x406);
            byte[] data = new byte[6];
            while (true)
            {
                WaitForSingleObject(hEvent, -1);
                ResetEvent(hEvent);
                Array.Clear(ioctlBuf, 0, ioctlBuf.Length);
                nRet = (uint)ioctlBuf.Length;
                Array.Copy(BitConverter.GetBytes((short)0x708), ioctlBuf, 2);
                Array.Copy(BitConverter.GetBytes(bufIndex), 0, ioctlBuf, 2, 4);
                DeviceIoControl(hDevice, 0x9c412000, ioctlBuf, nRet, ioctlBuf, nRet, out nRet, IntPtr.Zero);
                int count = BitConverter.ToInt32(ioctlBuf, 10);
                bufIndex = BitConverter.ToInt32(ioctlBuf, 0x480e);

                for (int i = 0; i < count; ++i)
                {
                    byte d1 = ioctlBuf[14 + i * 18 + 4];
                    int d4 = BitConverter.ToInt32(ioctlBuf, 14 + i * 18 + 13);
                    byte d5 = ioctlBuf[14 + i * 18 + 17];
                    data[d4] = d5;
                    if (d4 == 5)
                    {
                        if (d1 == 16 && data[1] == 0) //release
                        {
                            X = Y = 0;
                        }
                        else if (d1 == 17)
                        {
                            X = (data[1] & 0xf) * 0x100 + data[2];
                            Y = (data[4] & 0xf) * 0x100 + data[5];
                        }
                    }
                }
            }
        }
    }
}
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Microsoft.Ink;
using System.IO;
using System.Runtime.InteropServices;


namespace InkTest
{
    public partial class Form1 : Form
    {
        List<Point> mPoints = new List<Point>();
        Ink mInk = new Ink();
        int mLastX, mLastY;
        DateTime mLastTime = DateTime.MaxValue;
        [DllImport("user32")]
        static extern int GetKeyState(int nVirtKey);

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            ETD.Init();
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            //this.Hide();
            if (GetKeyState(0xA0) > 0)
                return;
            if (ETD.X == 0 && ETD.Y == 0)
            {
                if (mLastX != 0 && mLastY != 0)
                {

                    mInk.Strokes.Add(mInk.CreateStroke(mPoints.ToArray()));
                    mPoints.Clear();
                    mLastTime = DateTime.Now;
                }
                else if (DateTime.Now - mLastTime > TimeSpan.FromSeconds(0.5))
                {
                    string str = mInk.Strokes.ToString();
                    mInk.DeleteStrokes();
                    mLastTime = DateTime.MaxValue;
                    Clipboard.SetText(str);
                    SendKeys.Send("^V");
                }
            }
            else
            {
                mPoints.Add(new Point(ETD.X, -ETD.Y));
            }
            mLastX = ETD.X;
            mLastY = ETD.Y;
            this.Text = string.Format("{0},{1}", ETD.X, ETD.Y);
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            Environment.Exit(0);
        }
    }
}

硬链接问题:不应使用Xcopy移动C:\Program Files目录到数据盘

有一些文章提到了可以使用xcopy将C:\Program Files、C:\Program Files (x86)、C:\ProgramData、C:\Users移动到D盘,然后在C盘建立NTFS符号链接以减少空间占用。例如:

xcopy /e /h /k /x /y /b /c “C:\Program Files” “D:\Program Files”
rd /s “C:\Program Files”
mklink /j “C:\Program Files” “D:\Program Files”

笔者有一段时间也这样做过,但最近经过深入研究,发现这样做忽视了一个很大的问题——NTFS硬链接。

windows vista以上,所有系统文件的实际上均存放在winsxs目录中,然后在system32或syswow64目录下建立硬链接,这样实际上只占用一份空间。安装更新时也是这样做,新文件与旧文件并存,然后将硬链接改到新的文件上。删除文件时,必须将一个文件所有的“指针”都删除文件才会真正删除。

wim镜像支持NTFS硬链接的保存,通过imagex /info可以看到,安装盘中有4G的文件是存在硬链接的。

这样一来移动Program Files到D盘对于windows自带软件,如ie、wmp等完全无法起到省空间的作用,因为它们在winsxs中还有一份指针。并且就算是以后再移动回来,硬链接也无法恢复,还是会多占用一份空间。

另外,由于该问题,使用目录符号链接将C:\Program Files指向D:\Program Files会造成windows update对ie等软件更新失败,因为自动更新无法在已经符号链接到D盘的Program Files目录中创建指向winsxs的硬链接。网上也有人遇到过,说将注册表Program Files目录改为D盘即可,然而没人搞清楚为什么。

硬链接只有在安装系统、安装更新时能够自动地建立。一旦破坏,除了微软没人知道应该怎么科学地重建。如果是换硬盘而不想重装系统,千万不能使用xcopy,而要使用基于文件系统的拷贝,如imagex捕获镜像再应用到新盘上,或ghost partition to partition。否则在win7下最少会造成5G空间浪费,在win8和win10上由于自带显卡驱动包这个数字可能高达几十G。

Users目录倒是可以移动到D盘然后建立符号链接,不过个人建议只动自己的用户目录。

适用于开启与WinXP/2003兼容的标准用户的Win7/2008R2 UAC设置

题目有点绕。需求是这样的:在WinXP/2003下,标准用户组Users具有一般的使用权,但不能对系统进行更改,在那个没有UAC的时代,合理配合使用Users组和手动提权到Administrator,其实也是可以做到和现在有UAC时同等安全地裸奔的(但很可惜那个时代我修电脑的认知还停留在Win98的水平,对NT系统的强大了解甚少,一度认为XP系统很不安全,连自己都装过卡巴死机和360,黑历史不堪回首)。

在标准用户组下,所有程序本身都能运行的,但进行需要权限的操作会直接Access Denied失败。使用标准用户的case还是有使用的地方的,适合于非IT工作单位或家庭、有网管的情况。例如豆子每次回家都会表示自己家中的电脑被装了各种全家桶,考虑到豆子并不能随时向豆爸普及正确使用电脑的知识(这点和我家情况不一样,我爸本来电脑水平并不弱,我是真IT所以多年来一直在黑国产软件而且我爸还是注重隐私的。但最近也有点hold不住,因为我妈,最近回家电脑上都会多了TB浏览器啊,文件默认关联变成QQ音乐啊,至于为什么不是全家桶估计因为阿里没做杀软吧),我建议他直接给受限帐户,常用软件弄好,不允许新软件的安装。

然而豆子配置后表示,不给力啊。在Win7/2008R2下,标准用户遇到需要提权的情况时还是会蹦安全桌面,要求输入管理员的密码,这不是等于明摆着告诉豆爸我把你电脑锁了请打电话找我要密码。好的我们有组策略,组策略里可以设置标准用户的提权操作为拒绝提权。结果这样一来任何要求提权的软件均不能启动,包括计算机管理、配置了manifest的exe以及文件名中带有setup字样的exe,提示组策略禁止了该软件启动请与管理员联系。好吧软件都没法启动了还用个毛啊。

我们需要的是像WinXP/2003那样,软件还能用但是干不了啥流氓事。这个问题我当时实验了不少设置没有成功,后来一度搁置了,主要是网上没有搜索到类似的案例,也许是这个问题描述不好总结出关键词搜索。UAC是在程序运行前的,显然我们没法去把所有程序的manifest去掉。三个月前因为这个问题把家里的电脑换回了xp。

今天帮忙优化工作室的电脑,那种ghost win7的版本,默认administrator帐户,试着开一个普通的受限用户,结果需要提权的时候uac并没有蹦出来弄的反而提不了,所有程序右下角也没有小盾牌,需要权限的程序也能以受限权限运行,点任务管理器里的显示所有用户进程怎么点都会重启任务管理器,但是还是受限权限,计算机管理也能以受限权限打开(但打不开磁盘管理)。这很奇怪,和我当时做实验时不一致。

一度以为是ghost win7直接把uac阉割了,但没查到具体怎么做的,但无论如何,这说明我想要的这个功能在win7中还是能实现的。自己再做实验时无意中按照一篇文章中说的把HKLM\Software\Microsoft\Windows\CurrentVersion\Policies\System中EnableLUA设为0,然后重启,居然成功了。后来再进一步看,发现这货就是组策略中的“管理员审批模式”设为禁用或者控制面板中UAC设置中最低一级的完全关闭嘛。当时做实验时应该也有试过这样的操作,但为什么没成功现在不得而知。

总之,结论是如果需要在Win7/2008R2中使用WinXP/2003中的受限用户,则应将UAC彻底关闭,否则所有带有manifest的程序均无法直接运行而是会弹UAC密码框。关闭UAC后,右键的管理员权限运行还在,但是不起作用,若想避免切换用户提权,需要按住shift右键选择以指定用户运行,然后输入管理员的用户名和密码,但这时程序实际运行的帐户也将是另外的帐户,环境变量也是另外的帐户的,例如AppData不再指向当前帐户的目录。