JMC31337 Posted November 30, 2013 Posted November 30, 2013 (edited) #include <windows.h> //DEV-C++ //link with -masm=intel asm(".intel_syntax noprefix"); static long csx; static char* test; int main(void) { asm("pop ebp"); asm("pop ebp"); asm("pop ebp"); //asm("push 0x11111111"); //asm("push 0xEEEEEEEE"); //asm("push 0xAAAAAAAA"); //asm("push 0xCCCCCCCC"); //char *test = "\x31\xC9\x51\x68" //"\x63\x61\x6C\x63" //"\x54\xB8\xC7\x93" //"\xC2\x77\xFF\xD0"; asm("push 0xD0FF77C2"); asm("push 0x93C7B854"); asm("push 0x636C6163"); asm("push 0x6851C931"); asm("push 0x004012E6"); asm("mov ebp,0x33333333"); asm("mov edx, esp"); asm("SYSENTER"); asm("push 0"); asm("call _ExitProcess@4"); asm("call esp"); return 0; } nothing too major from what i can tell. But it was neat to use SYSENTER to pop this calc shellcode on XP SP3seems to go into kernel then back to the user mode call esp. Since the shellcode for calc was placed there in esp, it popsMaybe a call esp located in ntoskernl would be better to try but the PoC is here to play with and it sucks the mem addresses are hardcoded which means they have a possibility of changing between systemsbut shellcode is great for avoiding APIno clean exit (i was too lazy) lastly: we can call esp from ntdll: asm("push 0x7C95D003"); instead asm("push 0x004012E6"); Edited December 1, 2013 by JMC31337
kao Posted December 1, 2013 Posted December 1, 2013 Are you practicing for obfuscated code contest? Because yet again I fail to see any security discovery here.1) This is shellcode you're using:31C9 XOR ECX,ECX <-\ 51 PUSH ECX <-- put 0 to stack to have "calc" string 0-terminated.68 63616C63 PUSH 636C6163 <-- put string "calc" on stack54 PUSH ESP <-- push pointer to that stringB8 C793C277 MOV EAX,77C293C7 <-- hardcoded address of msvcrt!system APIFFD0 CALL EAX <-- call msvcrt!systemWe can see the same shellcode at http://www.exploit-db.com/exploits/17302/ and http://www.exploit-db.com/exploits/22467/ and in gazillion of other places. And it's definitely not avoiding APIs.2) Behaviour of SYSENTER and KiFastSystemCall is well documented, for example here: http://www.geoffchappell.com/studies/windows/km/cpu/sep.htm
JMC31337 Posted December 1, 2013 Author Posted December 1, 2013 (edited) yea thats pretty much a standard shellcode to pop calc (i never said otherwise)and yea shellcode does avoid API http://www.symantec.com/connect/articles/windows-syscall-shellcode Syscall shellcode advantagesThere are several advantages when using this approach: Shellcode doesn't require the use of APIs, due to the fact that it doesn't have to locate API addresses (there is no kernel address finding/no export section parsing/import section parsing, and so on). Due to this "feature" it is able to bypass most of ring3 "buffer overflow prevention systems." Such protection mechanisms usually don't stop the buffer overflow attacks in itself, but instead they mainly hook the most used APIs and check the caller address. Here, such checking would be of no use.Since you are sending the requests directly to the kernel handler and you "jump over" all of those instructions from the Win32 Subsystem, the speed of execution highly increases (although in the era of modern processors, who truly cares about speed of shellcode?).Syscall shellcode disadvantagesThere are also several disadvantages to this approach: Size -- this is the main disadvantage. Becase we are "jumping over" all of those subsytem wrappers, we need to code our own ones, and this increases the size of shellcode.Compability -- as has been written above, there exist various implementations from "int 2eh" to "sysenter," depending on the operating system version. Also, the system call number changes together with each Windows version (for more see the References section).nowhere did i ever say this post ever exploited something... just said it pops calcand if you can find me another SYSENTER popper post it, because im interested PS: i bet i could code an entire virus using nothing but SYSENTER Edited December 1, 2013 by JMC31337
JMC31337 Posted December 1, 2013 Author Posted December 1, 2013 (edited) here's what ollydbg showsCPU DisasmAddress Hex dump Command Comments004012DD |. 0F34 SYSENTER hit F7 and step into that there SYSENTER one time and here is the register output: CPU - main thread, module ntdll EAX C0000005ECX 00000001EDX FFFFFFFFEBX 00004000ESP 0022FF5CEBP 33333333ESI 7E471088EDI 7E418BD9EIP 7C95D003 ntdll.7C95D003 C 1 ES 0023 32bit 0(FFFFFFFF)P 1 CS 001B 32bit 0(FFFFFFFF)A 0 SS 0023 32bit 0(FFFFFFFF)Z 1 DS 0023 32bit 0(FFFFFFFF)S 0 FS 003B 32bit 7FFDF000(FFF)T 0 GS 0000 NULLD 0O 0 LastErr 00000002 ERROR_FILE_NOT_FOUNDEFL 00000247 (NO,B,E,BE,NS,PE,GE,LE) ST0 empty +UNORM 4729 5AD74729 5ADA1178ST1 empty 0.0ST2 empty 0.0ST3 empty +UNORM 0054 00000000 01000000ST4 empty 0.0000000000231729020e-4933ST5 empty 0.0ST6 empty 0.0ST7 empty -UNORM FFF5 00000000 00000000 3 2 1 0 E S P U O Z D IFST 0000 Cond 0 0 0 0 Err 0 0 0 0 0 0 0 0 (GT)FCW 037F Prec NEAR,64 Mask 1 1 1 1 1 1Last cmnd 0000:00000000 XMM0 0061006D 006F0068 00610054 00000000XMM1 0061006D 006F0068 00610054 00000000XMM2 00000000 00000000 00000000 00000000XMM3 00000000 00000000 00000000 00000000XMM4 5AD746C1 5AD746AD 0012B53C 0000F920XMM5 0012B758 5AD753A4 0012B758 5ADA113CXMM6 00A3808C 00A38444 00A38130 5AD8CD4DXMM7 5AD75904 0012B77C 003A0900 5AD753FC P U O Z D IMXCSR 00001F80 FZ 0 DZ 0 Err 0 0 0 0 0 0 Rnd NEAR Mask 1 1 1 1 1 1 That EAX according to Symantec is the syscall ordinal number which says from my experience C0000005 ACCESS VIOLATION but we say whatever, we're gonna keep running this syscallthat calls POP CALCULATOR but hey mayber on your system c0000005 isnt access violation i dunnoor maybe i miss the point of this whole tutorial and the EDX FFFFFFFF:is MCSFT's wonderful SEH which isnt helping in this situation at all Edited December 1, 2013 by JMC31337
kao Posted December 2, 2013 Posted December 2, 2013 You're mixing apples and oranges. 1) As my disassembly clearly shows - your shellcode is using msvcrt API "system". That's an API, not a syscall.2) You could also read the original PB's article about shellcode using only syscalls: http://pb.specialised.info/all/articles/windows_syscall_shellcode.pdf and then look at your shellcode again.3) Your OllyDbg "analysis" makes absolutely no sense - for too many reasons to list them all here. My suggestion - read some beginners books first - and then try doing research.
JMC31337 Posted December 2, 2013 Author Posted December 2, 2013 (edited) You're mixing apples and oranges. 1) As my disassembly clearly shows - your shellcode is using msvcrt API "system". That's an API, not a syscall. 2) You could also read the original PB's article about shellcode using only syscalls: http://pb.specialised.info/all/articles/windows_syscall_shellcode.pdf and then look at your shellcode again. 3) Your OllyDbg "analysis" makes absolutely no sense - for too many reasons to list them all here. My suggestion - read some beginners books first - and then try doing research. CPU Disasm Address Hex dump Command Comments 004011E7 |. 89C3 MOV EBX,EAX 004011E9 |. E8 C2050000 CALL <JMP.&msvcrt._cexit> ; [MSVCRT._cexit 004011EE |. 891C24 MOV DWORD PTR SS:[ESP],EBX ; /ExitCode 004011F1 |. E8 7A060000 CALL <JMP.&KERNEL32.ExitProcess> ; \KERNEL32.ExitProcess thats where i ended up before exiting with our lil pdf TerminateProcess using SYSENTER so plz.. spare me.. and your tutorial is the same as mine, which hard codes NTDLL mem addresses just like my very original asm code... Back to MCSFT you go! Edited December 2, 2013 by JMC31337
Peter Ferrie Posted December 2, 2013 Posted December 2, 2013 You're simply imagining things that aren't happening. Your syscall *is returning to user mode* with an error code of 0xc0000005. It resumes execution at the address that was pushed on the stack. That is the offset of your call esp. Then it runs the code that you pushed on the stack, which calls the hardcoded *API* address in msvcrt.dll to execute calc.exe. You're not running anything at all via that syscall. You didn't even pass the syscall a valid ID in the first place, which is why you have an error code in eax.
JMC31337 Posted December 2, 2013 Author Posted December 2, 2013 (edited) fine fine.. then why does your MCSFT windbg says EXPLOITABLE? and how about this: int main(){asm("mov eax, 0x101");asm("push 0x7C81D233");asm("mov edx,esp");asm("SYSENTER");return 0; } we're gonna fig this out.. CPU DisasmAddress Hex dump Command Comments004012BA |. B8 01010000 MOV EAX,101004012BF |. 68 33D2817C PUSH 7C81D233004012C4 |. 89E2 MOV EDX,ESP004012C6 |. 0F34 SYSENTER then we hit:CPU DisasmAddress Hex dump Command Comments7C81D233 8BFF MOV EDI,EDI ; BOOL kernel32.TerminateThread(hThread,ExitCode) and cleanly exit Edited December 2, 2013 by JMC31337
kao Posted December 3, 2013 Posted December 3, 2013 First, it will try to call NtTerminateProcess via syscall. Since you're providing invalid parameters, the call will fail with status 0xC0000008 - invalid handle.It will return to KiFastSystemCallRet - which will then jump to the address you specified (TerminateThread). If you had read anything about syscalls in WinXP (see, for example, link in my post #2), you'd know that.
JMC31337 Posted December 3, 2013 Author Posted December 3, 2013 asm("push 0x7C81D233");asm("mov edx,esp");asm("SYSENTER");changed the Sysenter to RET causing the top of stack to be jumped to MSVCRTwhereas:asm("mov eax, 0x102");asm("mov edx, 0x7C81D233");asm("call dword ptr edx"); (or sysenter)goes to the k32.TerminateThread which then exitsCompletely different placesAnd in the original post i mention it was coming back down to user mode and also never said it was an exploit ... Windbg did
JMC31337 Posted December 3, 2013 Author Posted December 3, 2013 (edited) *After checking with replacement of SYSENTER and RET i see that it does go to BOOL kernel32.TerminateThread(hThread,ExitCode)as does the SYSENTER call ... Guess ill have to code a lil replication virus just for fun if i can; with sysenter but here is a situation in which i get different results with RET: asm("mov eax, 0x102");asm("mov ebx, 0x7C81D233");asm("mov edx,ebx");asm("ret");takes me to MSVCRT whereas:asm("mov eax, 0x102");asm("mov ebx, 0x7C81D233");asm("mov edx,ebx");asm("call edx");takes me to the TerminateThread if i try a sysenter i end up in the NtTerminateThreadasm("mov eax, 0x102");asm("mov ebx, 0x7C81D233");asm("mov dword ptr [edx],ebx");asm("SYSENTER"); here are the printouts before i run the sysenter:CPU - main thread, module SysTermEAX 00000102ECX 00401310 SysTerm.00401310EDX 77C61AE8 msvcrt.77C61AE8EBX 7C81D233 kernel32.TerminateThreadESP 0022FF60EBP 0022FF78ESI 7E471088EDI 7E418BD9EIP 004012C6 SysTerm.004012C6 and after the SYSENTER:CPU - main thread, module kernel32EAX C00000DBECX 00000001EDX FFFFFFFFEBX 7C81D233 kernel32.TerminateThreadESP 77C61AEC msvcrt.77C61AECEBP 0022FF78ESI 0012B3FCEDI 7C901000 ntdll.RtlEnterCriticalSectionEIP 7C81D233 kernel32.TerminateThread Ending with an FFFFFFFF and hang app-ing my olly (however, just running the exe causes no probs) Edited December 3, 2013 by JMC31337
JMC31337 Posted December 3, 2013 Author Posted December 3, 2013 and to take it to the next level asm("mov eax, 0x102");asm("mov ebx, 0x7C81D233");asm("mov dword ptr [edx],ebx");asm("push edx");asm("SYSENTER");takes me to the TerminateThread asm("mov eax, 0x102");asm("mov ebx, 0x7C81D233");asm("mov dword ptr [edx],ebx");asm("push edx");asm("ret");does not take me to Terminate Thread
kao Posted December 3, 2013 Posted December 3, 2013 Yes, you really took it to the next level. You discovered that "ret" instruction actually returns and "call" instruction actually calls. Great work!In next few months maybe you'll learn the difference between "mov edx, ebx" and "mov dword ptr [edx], ebx". But until then... Oh well... 1
JMC31337 Posted December 3, 2013 Author Posted December 3, 2013 asm("SYSENTER");Seems to call the ptr to edxWhereas push that edx onto the stack and calling that with a RETDoes not goto the ptr of edxSo SYSENTER goes to ptr edxRET does not, unless you push dword ptr So... It has nothing to do with call jmp and everything to do with how SYSENTER is handled in the system... I'll try to do a kernel create writefile just to play... Somehow you both came at it like this was some exploit when from the gate I said it was nothing serious ... But thanks for not bringing anything to the table besides a PDF that I already posted, and bashing me for playing with shellcode
JMC31337 Posted December 5, 2013 Author Posted December 5, 2013 (edited) this is SYSENTER calling LoadLibrary char *xnt = "ntdll.dll"; int main() { asm("xor eax,eax"); asm("xor ebx,ebx"); asm("xor ecx,ecx"); asm("xor edx,edx"); asm("push dword ptr _xnt"); asm("push 0"); asm("push 0x7C801D7B"); asm("mov eax,[esp+8]"); asm("mov dword ptr [esp+12], eax"); asm("mov edx,esp"); asm("mov dword ptr [esp+0x04],0x004012E3"); asm("SYSENTER"); asm("ret"); } Edited December 5, 2013 by JMC31337
kao Posted December 5, 2013 Posted December 5, 2013 Again you are imagining things that aren't happening. SYSENTER is not calling LoadLibrary. Re-read posts #7 and #9, they describe what's really happening. Re-read document I linked in #2. If you still don't get it, I don't know who/what can help you.
JMC31337 Posted December 5, 2013 Author Posted December 5, 2013 (edited) Again you are imagining things that aren't happening. SYSENTER is not calling LoadLibrary.Re-read posts #7 and #9, they describe what's really happening. Re-read document I linked in #2.If you still don't get it, I don't know who/what can help you.yea you're not hiding this one there buddy: CPU DisasmAddress Hex dump Command Comments004012E1 |. 0F34 SYSENTER there is sysenter -> CPU DisasmAddress Hex dump Command Comments7C801D7B 8BFF MOV EDI,EDI ; HANDLE kernel32.LoadLibraryA(FileName) which further loads up the NTDLL file for me: CPU - main thread, module kernel32 EAX 7C900000 ntdll.7C900000 and lets dump that just to be sure: CPU DumpAddress Hex dump ASCII7C900000 4D 5A 90 00|03 00 00 00|04 00 00 00|FF FF 00 00| MZ.........7C900010 B8 00 00 00|00 00 00 00|40 00 00 00|00 00 00 00| .......@.......7C900020 00 00 00 00|00 00 00 00|00 00 00 00|00 00 00 00| ................7C900030 00 00 00 00|00 00 00 00|00 00 00 00|D0 00 00 00| ...............7C900040 0E 1F BA 0E|00 B4 09 CD|21 B8 01 4C|CD 21 54 68| ..!L!Th7C900050 69 73 20 70|72 6F 67 72|61 6D 20 63|61 6E 6E 6F| is program canno7C900060 74 20 62 65|20 72 75 6E|20 69 6E 20|44 4F 53 20| t be run in DOS7C900070 6D 6F 64 65|2E 0D 0D 0A|24 mode....$ sysenter doesnt just CALL ESP, it calls EDXAnd its the only OPCODE im using to "CALL" something (hence SYSTEM CALL)onward with GetProcAddress then ZwQuerySystemInformation then ZwCreateFile so i can use nothing but Kernel calls to write a 0-byte file to your C drive root Edited December 5, 2013 by JMC31337
deepzero Posted December 5, 2013 Posted December 5, 2013 (edited) maybe these two pictures will clear it up. In both cases we are standing at the sysenter command, if you hit f8 now, the effect in question will occur: we will return from sysenter with an error code and eip will be eip == LoadLibraryA == [edx], and because of your "mov edx, esp" also edx == esp => [edx] == [esp]. now, if you had read Kao's link, you would have read this: When SYSEXIT is called, CS is set to IA32_SYSENTER_CS+16. EIP is set to EDX. SS is set to IA32_SYSENTER_CS+24, and ESP is set to ECX. and indeed, after the sysenter eip == [edx] == LoadLibraryA To prove this to you, if have altered the situation a tiny little bit: edx == [esp+4] == LoadLibraryW. picture: and sure enough, once you step over the sysenter, you will be at LoadLibraryW. Because LoadLibraryW == eip == [edx], as per the documentation. which is pretty much what Peter Ferrier told you earlier: Your syscall *is returning to user mode* with an error code of 0xc0000005. It resumes execution at the address that was pushed on the stack. alright? Edited December 5, 2013 by deepzero
JMC31337 Posted December 5, 2013 Author Posted December 5, 2013 (edited) and i understand that its just a user mode call and that we havent ran anything as SYSTEM (like an Kernel APC process giving NTAUTHORITY/SYSTEM as the user) but what im trying to do is use that fact that the c0000005 access violation DOESNT kick it back to the program space until after the loadlibrary loads ntdll sysenter kicks into a syscall which then keeps on running loadlibrary until its finished then kicking it back to our program user mode space thats why i added the RET after sysenter.. it doesnt end up at RET until AFTER SYSENTER does its thing now if that c000005 stopped the sysenter with that ACCESS VIOLATION .,.. loadlibrary would never grab me my ntdll module address but it still lets the code continue... at first i called into the NOP region above the loadlibrary and let it nop sled into the LoadLibrary ... if that C000005 would stop the sysenter it would never sled down the nops into the LoadLibrary.. it should not allow me to do that.. once it access violations out, that whole process should stop running .. at one point it was just calling into load and then coming back down, and because i didnt have the ESP correct (it was pointing again at SYSENTER) it SYSENTER looped on me... but the 2nd time sysenter did its thing the ESP changed and crapped out on me.. which is why i added that push address pointing to the RET statement Edited December 5, 2013 by JMC31337
deepzero Posted December 5, 2013 Posted December 5, 2013 you dont call anything. thats why i added the RET after sysenter.. it doesnt end up at RET until AFTER SYSENTER does its thing it never hits that ret after sysenter. When sysenter returns to usermode, it doesnt continue after the sysenter instruction, it continues at [edx]. Now, if [edx] happens to point to LoadLibraryA, it will continue there. And if your stack *happens to be* layed out in a way that it returns to address x after the LoadLibraryA call, then it will continue at that address x. But that is standard execution and has nothing to do with sysret.Since you are providing invalid arguments for the syscal anyways, you can replace it byjmp dword [edx]jmp, not call.
JMC31337 Posted December 5, 2013 Author Posted December 5, 2013 on this system it gets to that ret and that ret was placed there by me to see what happens after sysenter comes back down.. here lemme add something else.. like some pops and show ya it still flows
JMC31337 Posted December 5, 2013 Author Posted December 5, 2013 (edited) take a look at the EIP poiting to the RET about to be called i added that breakpoint after sysenter (again to help me see what the EAX return was which is the NTDLL module base address which then helps with GetProcAddress) [but i left that register printout "out" of the pic] Edited December 5, 2013 by JMC31337
deepzero Posted December 5, 2013 Posted December 5, 2013 that is because of the way you set up your stack. Replace sysenter by jmp [edx] and you will observe the same effect.
JMC31337 Posted December 5, 2013 Author Posted December 5, 2013 naaa naaa lets not give the run-around reply here: "it never hits that ret after sysenter. When sysenter returns to usermode, it doesnt continue after the sysenter instruction, it continues at [edx]." it continues after the sysenter instruction okay.. and ultimately, all im doing is using the sysenter to GO SOMEWHERE ... and the "jmp [edx]" is just another obfuscated way of doing the SAME SYSENTER (go somewhere) routinecould very well jmp [eax] if its loaded right and end up at the same place... but nice spin-master reply... "that is because of the way you set up your stack" of course!im the one writing the thing.... anyways.. this argument ran its course.. lets argue again over this after i do a lil GetProcAddressingits a good time....
deepzero Posted December 5, 2013 Posted December 5, 2013 (edited) to GO SOMEWHERE ... correct, namely to [edx]. and the "jmp [edx]" is just another obfuscated way of doing the SAME SYSENTER (go somewhere) routine correct, in this limited case sysenter == jmp [edx] could very well jmp [eax] if its loaded right and end up at the same place... no, it's always [edx]. I want to stress again that execution *never* continues after the sysenter. It will continue at the address given on the stack. you set that here: move [locale.8], 4012e3 4012e3 *happens* to point after the sysenter - but you can use any other address in its place. Edited December 5, 2013 by deepzero
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now