Skip to content

Instantly share code, notes, and snippets.

@q3k
Last active April 14, 2024 17:11
Show Gist options
  • Star 70 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save q3k/af3d93b6a1f399de28fe194add452d01 to your computer and use it in GitHub Desktop.
Save q3k/af3d93b6a1f399de28fe194add452d01 to your computer and use it in GitHub Desktop.
liblzma backdoor strings extracted from 5.6.1 (from a built-in trie)
0810 b' from '
0678 b' ssh2'
00d8 b'%.48s:%.48s():%d (pid=%ld)\x00'
0708 b'%s'
0108 b'/usr/sbin/sshd\x00'
0870 b'Accepted password for '
01a0 b'Accepted publickey for '
0c40 b'BN_bin2bn\x00'
06d0 b'BN_bn2bin\x00'
0958 b'BN_dup\x00'
0418 b'BN_free\x00'
04e0 b'BN_num_bits\x00'
0790 b'Connection closed by '
0018 b'Could not chdir to home directory %s: %s\n\x00'
00b0 b'Could not get agent socket\x00'
0960 b'DISPLAY='
09d0 b'DSA_get0_pqg\x00'
0468 b'DSA_get0_pub_key\x00'
07e8 b'EC_KEY_get0_group\x00'
0268 b'EC_KEY_get0_public_key\x00'
06e0 b'EC_POINT_point2oct\x00'
0b28 b'EVP_CIPHER_CTX_free\x00'
0838 b'EVP_CIPHER_CTX_new\x00'
02a8 b'EVP_DecryptFinal_ex\x00'
0c08 b'EVP_DecryptInit_ex\x00'
03f0 b'EVP_DecryptUpdate\x00'
00f8 b'EVP_Digest\x00'
0408 b'EVP_DigestVerify\x00'
0118 b'EVP_DigestVerifyInit\x00'
0d10 b'EVP_MD_CTX_free\x00'
0af8 b'EVP_MD_CTX_new\x00'
06f8 b'EVP_PKEY_free\x00'
0758 b'EVP_PKEY_new_raw_public_key\x00'
0510 b'EVP_PKEY_set1_RSA\x00'
0c28 b'EVP_chacha20\x00'
0c60 b'EVP_sha256\x00'
0188 b'EVP_sm'
08c0 b'GLIBC_2.2.5\x00'
06a8 b'GLRO(dl_naudit) <= naudit\x00'
01e0 b'KRB5CCNAME\x00'
0cf0 b'LD_AUDIT='
0bc0 b'LD_BIND_NOT='
0a90 b'LD_DEBUG='
0b98 b'LD_PROFILE='
03e0 b'LD_USE_LOAD_BIAS='
0a88 b'LINES='
0ac0 b'RSA_free\x00'
0798 b'RSA_get0_key\x00'
0918 b'RSA_new\x00'
01d0 b'RSA_public_decrypt\x00'
0540 b'RSA_set0_key\x00'
08f8 b'RSA_sign\x00'
0990 b'SSH-2.0'
04a8 b'TERM='
00e0 b'Unrecognized internal syslog level code %d\n\x00'
0158 b'WAYLAND_DISPLAY='
0878 b'__errno_location\x00'
02b0 b'__libc_stack_end\x00'
0228 b'__libc_start_main\x00'
0a60 b'_dl_audit_preinit\x00'
09c8 b'_dl_audit_symbind_alt\x00'
08a8 b'_exit\x00'
05b0 b'_r_debug\x00'
05b8 b'_rtld_global\x00'
0a98 b'_rtld_global_ro\x00'
00b8 b'auth_root_allowed\x00'
01d8 b'authenticating'
0028 b'demote_sensitive_data\x00'
0348 b'getuid\x00'
0a48 b'ld-linux-x86-64.so'
07d0 b'libc.so'
07c0 b'libcrypto.so'
0590 b'liblzma.so'
0938 b'libsystemd.so'
0020 b'list_hostkey_types\x00'
0440 b'malloc_usable_size\x00'
00c0 b'mm_answer_authpassword\x00'
00c8 b'mm_answer_keyallowed\x00'
00d0 b'mm_answer_keyverify\x00'
0948 b'mm_answer_pam_start\x00'
0078 b'mm_choose_dh\x00'
0040 b'mm_do_pam_account\x00'
0050 b'mm_getpwnamallow\x00'
00a8 b'mm_log_handler\x00'
0038 b'mm_pty_allocate\x00'
00a0 b'mm_request_send\x00'
0048 b'mm_session_pty_cleanup2\x00'
0070 b'mm_sshpam_free_ctx\x00'
0058 b'mm_sshpam_init_ctx\x00'
0060 b'mm_sshpam_query\x00'
0068 b'mm_sshpam_respond\x00'
0030 b'mm_terminate\x00'
0c58 b'parse PAM\x00'
0400 b'password\x00'
04f0 b'preauth'
0690 b'pselect\x00'
07b8 b'publickey\x00'
0308 b'read\x00'
0710 b'rsa-sha2-256\x00'
0428 b'setlogmask\x00'
05f0 b'setresgid\x00'
0ab8 b'setresuid\x00'
0760 b'shutdown\x00'
0d08 b'ssh-2.0'
02c8 b'ssh-rsa-cert-v01@openssh.com\x00'
0088 b'sshpam_auth_passwd\x00'
0090 b'sshpam_query\x00'
0080 b'sshpam_respond\x00'
0098 b'start_pam\x00'
09f8 b'system\x00'
0198 b'unknown\x00'
0b10 b'user'
0380 b'write\x00'
0010 b'xcalloc: zero size\x00'
0b00 b'yolAbejyiejuvnup=Evjtgvsh5okmkAvj\x00'
0300 b'\x7fELF'
@LevitatingBusinessMan
Copy link

Very nice!

@LevitatingBusinessMan
Copy link

Could you share your python code used for extracting?

@brlin-tw
Copy link

Can anyone explain the seemingly suspicious string at L115?

@q3k
Copy link
Author

q3k commented Mar 30, 2024

Here's the tooling I used to extract this: https://gist.github.com/q3k/3fadc5ce7b8001d550cf553cfdc09752 . This has tables extracted from the 5.6.1 Fedora build (https://koji.fedoraproject.org/koji/buildinfo?buildID=2417414).

@stan423321
Copy link

Can anyone explain the seemingly suspicious string at L115?

There's a theory this was one way to disable the malware (source).

@realazizk
Copy link

@stan423321 yeah it's a kill switch

@brlin-tw
Copy link

@stan423321 Thanks for the info, greatly appreciated!

@herzeleid02
Copy link

Is there any information about setlogmask section? That means the exploited SSH connections wouldnt be logged?

@workingjubilee
Copy link

Yes, setlogmask is a symbol where calls to it override previous calls, and it could be used to silence logging that went through syslog.

However, it's also possible that some of these symbols appear for a "non-malicious" reason: the code in question must still behave like the OpenSSH code it replaces, in order to evade immediate detection, so it may just be duplicating some of that code.

@tux3
Copy link

tux3 commented Mar 31, 2024

Same list as a rough C enum, in case it saves anyone 2 min :)
enum {usr_sbin_sshd = 0x108,Accepted_password_for = 0x870,Accepted_publickey_for = 0x1A0,BN_bin2bn = 0xC40,BN_bn2bin = 0x6D0,BN_dup = 0x958,BN_free = 0x418,BN_num_bits = 0x4E0,Connection_closed_by = 0x790,Could_not_chdir_to_home = 0x18,Could_not_get_agent_socket = 0xB0,DISPLAY_equal = 0x960,DSA_get0_pqg = 0x9D0,DSA_get0_pub_key = 0x468,EC_KEY_get0_group = 0x7E8,EC_KEY_get0_public_key = 0x268,EC_POINT_point2oct = 0x6E0,EVP_CIPHER_CTX_free = 0xB28,EVP_CIPHER_CTX_new = 0x838,EVP_DecryptFinal_ex = 0x2A8,EVP_DecryptInit_ex = 0xC08,EVP_DecryptUpdate = 0x3F0,EVP_Digest = 0xF8,EVP_DigestVerify = 0x408,EVP_DigestVerifyInit = 0x118,EVP_MD_CTX_free = 0xD10,EVP_MD_CTX_new = 0xAF8,EVP_PKEY_free = 0x6F8,EVP_PKEY_new_raw_public_key = 0x758,EVP_PKEY_set1_RSA = 0x510,EVP_chacha20 = 0xC28,EVP_sha256 = 0xC60,EVP_sm = 0x188,GLIBC_2_2_5 = 0x8C0,GLRO_dl_naudit_lte_naudit = 0x6A8,KRB5CCNAME = 0x1E0,LD_AUDIT_eq = 0xCF0,LD_BIND_NOT_eq = 0xBC0,LD_DEBUG_eq = 0xA90,LD_PROFILE_eq = 0xB98,LD_USE_LOAD_BIAS_eq = 0x3E0,LINES_eq = 0xA88,RSA_free = 0xAC0,RSA_get0_key = 0x798,RSA_new = 0x918,RSA_public_decrypt = 0x1D0,RSA_set0_key = 0x540,RSA_sign = 0x8F8,SSH_2_0 = 0x990,TERM_eq = 0x4A8,Unrecognized_internal_syslog_level_code_fmt = 0xE0,WAYLAND_DISPLAY_eq = 0x158,__errno_location = 0x878,__libc_stack_end = 0x2B0,__libc_start_main = 0x228,_dl_audit_preinit = 0xA60,_dl_audit_symbind_alt = 0x9C8,_exit = 0x8A8,_r_debug = 0x5B0,_rtld_global = 0x5B8,_rtld_global_ro = 0xA98,auth_root_allowed = 0xB8,authenticating = 0x1D8,demote_sensitive_data = 0x28,getuid = 0x348,ld_linux_x86_64_so = 0xA48,libc_so = 0x7D0,libcrypto_so = 0x7C0,liblzma_so = 0x590,libsystemd_so = 0x938,list_hostkey_types = 0x20,malloc_usable_size = 0x440,mm_answer_authpassword = 0xC0,mm_answer_keyallowed = 0xC8,mm_answer_keyverify = 0xD0,mm_answer_pam_start = 0x948,mm_choose_dh = 0x78,mm_do_pam_account = 0x40,mm_getpwnamallow = 0x50,mm_log_handler = 0xA8,mm_pty_allocate = 0x38,mm_request_send = 0xA0,mm_session_pty_cleanup2 = 0x48,mm_sshpam_free_ctx = 0x70,mm_sshpam_init_ctx = 0x58,mm_sshpam_query = 0x60,mm_sshpam_respond = 0x68,mm_terminate = 0x30,parse_PAM = 0xC58,password = 0x400,preauth = 0x4F0,pselect = 0x690,publickey = 0x7B8,read = 0x308,rsa_sha2_256 = 0x710,setlogmask = 0x428,setresgid = 0x5F0,setresuid = 0xAB8,shutdown = 0x760,ssh_2_0 = 0xD08,ssh_rsa_cert_v01_at_openssh_com = 0x2C8,sshpam_auth_passwd = 0x88,sshpam_query = 0x90,sshpam_respond = 0x80,start_pam = 0x98,system = 0x9F8,unknown = 0x198,user = 0xB10,write = 0x380,xcalloc_zero_size = 0x10,yolAbejyiejuvnup_eq_Evjtgvsh5okmkAvj = 0xB00,ELF_MAGIC = 0x300,from = 0x810,ssh2 = 0x678,pid_line_fmt = 0xD8,percent_s_fmt = 0x708}

@wanlill
Copy link

wanlill commented Mar 31, 2024

Can anyone explain the seemingly suspicious string at L115?

There's a theory this was one way to disable the malware (source).

I found this post because I dumped same list of strings and then googled yolAbejyiejuvnup=Evjtgvsh5okmkAvj.... I'm not sure whether this strange string is intended to be a kill switch but setting any string in the list as envar (e.g. LINES=, TERM=) will make the exploit stop early. It's checked in _Llzma_filter_decoder_is_supported_part_0 -> sub_3A10 -> _Lsimple_coder_update_0. This is why the original post mentioned that TERM, LD_DEBUG, LD_PROFILE need to be unset for exploit to work.

@karcherm
Copy link

karcherm commented Apr 1, 2024

They just run all environment variables through the trie. If it hits a leaf, the malware is killed. So TERM= (not NUL-terminated) is a hit if TERM has whatever value, same for DISPLAY= and WAYLAND_DISPLAY=. That's surely intended behaviour. I'm unsure whether the suspicious string is yet another killswitch, or it was intended for some other purpose - I didn't find a reference to the string ID 0xB00 yet, though.

As as side effect, all non-NUL-terminated strings in the list also work as variable name prefixes for a killswitch. So if you set EVP_sm=1234 or EVP_smd_components_soldering=difficult the backdoor is deactivated as well.

@Xinayder
Copy link

Xinayder commented Apr 2, 2024

So TERM= (not NUL-terminated) is a hit if TERM has whatever value, same for DISPLAY= and WAYLAND_DISPLAY=.

Could it be that the actor was explicitly targeting servers and not desktops?

@stan423321
Copy link

Could it be that the actor was explicitly targeting servers and not desktops?

This question is hard to directly answer as it depends on how you classify them. You could say no, because plugging in a screen wouldn't help. You could say yes, because desktops tend to not run Linux and sshd in the first place.

In context of environmental variables, however, this seems much more focused on skipping analysis of sshd, as that's when it will be invoked from some sort of regular work environment and not the daemon/service management one.

@karcherm
Copy link

karcherm commented Apr 3, 2024

So TERM= (not NUL-terminated) is a hit if TERM has whatever value, same for DISPLAY= and WAYLAND_DISPLAY=.

Could it be that the actor was explicitly targeting servers and not desktops?

The code is intended to affect sshd only, not any user-interactive process. So I don't think this is about servers versus desktops, but it is an attempt to only activate the injected code when sshd is invoked in the background from any kind of init system (like systemd), but not if sshd is started at an interactive command line (like sshd -h). It has been reported that "sshd -h" to display the help is slowed down considerably (but only if run in a "clean" environment). The "no TERM or DISPLAY" check seems to try to avoid exposure of the backdoor in the normal interactive use-case.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment