rofl0r / proxychains-ng

proxychains ng (new generation) - a preloader which hooks calls to sockets in dynamically linked programs and redirects it through one or more socks/http proxies. continuation of the unmaintained proxychains project. the sf.net page is currently not updated, use releases from github release page instead.
http://sourceforge.net/projects/proxychains-ng/files
GNU General Public License v2.0
9.79k stars 1.08k forks source link

macOS: ffmpeg failed to open remote file using sftp protocol over proxy (crash) #205

Open singular78 opened 6 years ago

singular78 commented 6 years ago

Environment:

Behavior:

ffmpeg can directly open remote file using sftp successfully, but failed over proxychains4.

Error:

~ ❯❯❯ proxychains4 ffmpeg -i sftp://john@192.168.3.2:/home/john/downloads/input.mp4 -r 24 output.avi -v trace
[proxychains] config file found: /usr/local/etc/proxychains.conf
[proxychains] preloading /usr/local/Cellar/proxychains-ng/4.12_1/lib/libproxychains4.dylib
[proxychains] DLL init: proxychains-ng 4.12
ffmpeg version 3.4 Copyright (c) 2000-2017 the FFmpeg developers
[NULL @ 0x7fa05b800000] Opening 'sftp://john@192.168.3.2:/home/john/downloads/input.mp4' for reading
[sftp @ 0x7fa059c09860] No default whitelist set
[proxychains] Strict chain  ...  127.0.0.1:8889  ...  192.168.3.2:22  ...  OK
Assertion failed: (ctx), function digest_update, file /BuildRoot/Library/Caches/com.apple.xbs/Sources/boringssl/boringssl-109.20.5/apple/crypto/digests.c, line 49.
[1]    473 abort      proxychains4 ffmpeg -i sftp://john@192.168.3.2:/home/john/downloads/input.mp4

Debug:

I use otool to confirm ffmpeg links the libssh of homebrew instead of macOS.

~ ❯❯❯ proxychains4 otool -L /usr/local/bin/ffmpeg
[proxychains] config file found: /usr/local/etc/proxychains.conf
[proxychains] preloading /usr/local/Cellar/proxychains-ng/4.12_1/lib/libproxychains4.dylib
/usr/local/bin/ffmpeg:
......
    /usr/local/opt/libssh/lib/libssh.4.dylib (compatibility version 4.0.0, current version 4.4.2)
......

ffmpeg and proxychains4 both don’t link the libboringssl, and why is it involved in the problem? I am not sure if the error is a proxychains4 issue.

rofl0r commented 6 years ago

do you get the line [proxychains] DLL init: proxychains-ng 4.12 several times ?

generally speaking, the error you get is because you either hit a bug in mac os' libc (very likely) or a bug in proxychains (less likely) which causes some sort of undefined behaviour, and it happens to manifest in that ssl lib. though i guess it could be interesting to debug what happens at that spot where the assertion fails.

singular78 commented 6 years ago

Debug proxychains4

Full Error:

The Line [proxychains] DLL init: proxychains-ng 4.12 only appears one time.

~/p/o/proxychains-ng ❯❯❯ proxychains4 ffmpeg -i sftp://john@localhost:/home/john/downloads/input.mp4 -r 24 output.avi -v trace                 tags/v4.12 ◼
[proxychains] config file found: /usr/local/etc/proxychains.conf
[proxychains] preloading /usr/local/Cellar/proxychains-ng/4.12_1/lib/libproxychains4.dylib
[proxychains] DLL init: proxychains-ng 4.12
ffmpeg version 3.4 Copyright (c) 2000-2017 the FFmpeg developers
  built with Apple LLVM version 9.0.0 (clang-900.0.38)
  configuration: --prefix=/usr/local/Cellar/ffmpeg/3.4 --enable-shared --enable-pthreads --enable-version3 --enable-hardcoded-tables --enable-avresample --cc=clang --host-cflags= --host-ldflags= --enable-gpl --enable-libmp3lame --enable-libssh --enable-libx264 --enable-libxvid --enable-opencl --enable-videotoolbox --disable-lzma
  libavutil      55. 78.100 / 55. 78.100
  libavcodec     57.107.100 / 57.107.100
  libavformat    57. 83.100 / 57. 83.100
  libavdevice    57. 10.100 / 57. 10.100
  libavfilter     6.107.100 /  6.107.100
  libavresample   3.  7.  0 /  3.  7.  0
  libswscale      4.  8.100 /  4.  8.100
  libswresample   2.  9.100 /  2.  9.100
  libpostproc    54.  7.100 / 54.  7.100
Splitting the commandline.
Reading option '-i' ... matched as input url with argument 'sftp://john@localhost:/home/john/downloads/input.mp4'.
Reading option '-r' ... matched as option 'r' (set frame rate (Hz value, fraction or abbreviation)) with argument '24'.
Reading option 'output.avi' ... matched as output url.
Reading option '-v' ... matched as option 'v' (set logging level) with argument 'trace'.
Finished splitting the commandline.
Parsing a group of options: global .
Applying option v (set logging level) with argument trace.
Successfully parsed a group of options.
Parsing a group of options: input url sftp://john@localhost:/home/john/downloads/input.mp4.
Successfully parsed a group of options.
Opening an input file: sftp://john@localhost:/home/john/downloads/input.mp4.
[NULL @ 0x7f85c7800000] Opening 'sftp://john@localhost:/home/john/downloads/input.mp4' for reading
[sftp @ 0x7f85c7409720] No default whitelist set
[proxychains] Strict chain  ...  127.0.0.1:8889  ...  127.0.0.1:22  ...  OK
Assertion failed: (ctx), function digest_update, file /BuildRoot/Library/Caches/com.apple.xbs/Sources/boringssl/boringssl-109.20.5/apple/crypto/digests.c, line 49.
[1]    22333 abort      proxychains4 ffmpeg -i sftp://john@localhost:/home/john/downloads/input.mp4

LLDB debug info of ffmpeg w/ proxychains4:

(lldb) r

......
[proxychains] Strict chain  ...  127.0.0.1:8889  ...  127.0.0.1:22  ...  OK
Assertion failed: (ctx), function digest_update, file /BuildRoot/Library/Caches/com.apple.xbs/Sources/boringssl/boringssl-109.20.5/apple/crypto/digests.c, line 49.
Process 22278 stopped
* thread #2, queue = 'com.apple.main-thread', stop reason = signal SIGABRT
    frame #0: 0x00007fff545e9fce libsystem_kernel.dylib`__pthread_kill + 10
libsystem_kernel.dylib`__pthread_kill:
->  0x7fff545e9fce <+10>: jae    0x7fff545e9fd8            ; <+20>
    0x7fff545e9fd0 <+12>: movq   %rax, %rdi
    0x7fff545e9fd3 <+15>: jmp    0x7fff545e176c            ; cerror_nocancel
    0x7fff545e9fd8 <+20>: retq
Target 0: (ffmpeg) stopped.

It is weird that digest_update is called. (lldb) bt

* thread #2, queue = 'com.apple.main-thread', stop reason = signal SIGABRT
  * frame #0: 0x00007fff545e9fce libsystem_kernel.dylib`__pthread_kill + 10
    frame #1: 0x00007fff54727150 libsystem_pthread.dylib`pthread_kill + 333
    frame #2: 0x00007fff5454630a libsystem_c.dylib`abort + 127
    frame #3: 0x00007fff5450e360 libsystem_c.dylib`__assert_rtn + 320
    frame #4: 0x00007fff52436520 libboringssl.dylib`digest_update + 51
    frame #5: 0x0000000101b30bac libcrypto.1.0.0.dylib`HMAC_Init_ex + 407
    frame #6: 0x00000001018dda53 libssh.4.dylib`hmac_init + 131
    frame #7: 0x00000001018dc287 libssh.4.dylib`match_hashed_host + 343
    frame #8: 0x00000001018dc81f libssh.4.dylib`ssh_knownhosts_algorithms + 206
    frame #9: 0x00000001018db52b libssh.4.dylib`set_client_kex + 211
    frame #10: 0x00000001018d6ae8 libssh.4.dylib`ssh_client_connection_callback + 382
    frame #11: 0x00000001018db32f libssh.4.dylib`ssh_packet_kexinit + 911
    frame #12: 0x00000001018e2e83 libssh.4.dylib`ssh_packet_process + 159
    frame #13: 0x00000001018e2c97 libssh.4.dylib`ssh_packet_socket_callback + 1230
    frame #14: 0x00000001018ea60c libssh.4.dylib`ssh_socket_pollcallback + 581
    frame #15: 0x00000001018e7e1e libssh.4.dylib`ssh_poll_ctx_dopoll + 226
    frame #16: 0x00000001018e8cdd libssh.4.dylib`ssh_handle_packets + 191
    frame #17: 0x00000001018e8b1d libssh.4.dylib`ssh_handle_packets_termination + 172
    frame #18: 0x00000001018d6857 libssh.4.dylib`ssh_connect + 629
    frame #19: 0x000000010038c3d2 libavformat.57.dylib`___lldb_unnamed_symbol868$$libavformat.57.dylib + 333
    frame #20: 0x000000010038bb98 libavformat.57.dylib`___lldb_unnamed_symbol858$$libavformat.57.dylib + 48
    frame #21: 0x000000010034707e libavformat.57.dylib`___lldb_unnamed_symbol196$$libavformat.57.dylib + 486
    frame #22: 0x0000000100347872 libavformat.57.dylib`ffurl_open_whitelist + 322
    frame #23: 0x0000000100349fa7 libavformat.57.dylib`___lldb_unnamed_symbol238$$libavformat.57.dylib + 36
    frame #24: 0x00000001003eb981 libavformat.57.dylib`___lldb_unnamed_symbol1555$$libavformat.57.dylib + 243
    frame #25: 0x0000000100432706 libavformat.57.dylib`avformat_open_input + 444
    frame #26: 0x000000010000a0af ffmpeg`___lldb_unnamed_symbol2$$ffmpeg + 1403
    frame #27: 0x00000001000099b6 ffmpeg`___lldb_unnamed_symbol1$$ffmpeg + 266
    frame #28: 0x00000001000097a4 ffmpeg`ffmpeg_parse_options + 179
    frame #29: 0x0000000100019cbc ffmpeg`main + 189
    frame #30: 0x00007fff5449a145 libdyld.dylib`start + 1
    frame #31: 0x00007fff5449a145 libdyld.dylib`start + 1

Debug info of ffmpeg w/o proxychains4

First, I set breakpoint on b HMAC_Init_ex.

(lldb) b HMAC_Init_ex
Breakpoint 2: 2 locations.
(lldb) r
Process 24872 launched: '/usr/local/bin/ffmpeg' (x86_64)
ffmpeg version 3.4 Copyright (c) 2000-2017 the FFmpeg developers
  built with Apple LLVM version 9.0.0 (clang-900.0.38)
  configuration: --prefix=/usr/local/Cellar/ffmpeg/3.4 --enable-shared --enable-pthreads --enable-version3 --enable-hardcoded-tables --enable-avresample --cc=clang --host-cflags= --host-ldflags= --enable-gpl --enable-libmp3lame --enable-libssh --enable-libx264 --enable-libxvid --enable-opencl --enable-videotoolbox --disable-lzma
  libavutil      55. 78.100 / 55. 78.100
  libavcodec     57.107.100 / 57.107.100
  libavformat    57. 83.100 / 57. 83.100
  libavdevice    57. 10.100 / 57. 10.100
  libavfilter     6.107.100 /  6.107.100
  libavresample   3.  7.  0 /  3.  7.  0
  libswscale      4.  8.100 /  4.  8.100
  libswresample   2.  9.100 /  2.  9.100
  libpostproc    54.  7.100 / 54.  7.100
Splitting the commandline.
Reading option '-i' ... matched as input url with argument 'sftp://byang@localhost:/home/byang/downloads/input.mp4'.
Reading option '-r' ... matched as option 'r' (set frame rate (Hz value, fraction or abbreviation)) with argument '24'.
Reading option 'output.avi' ... matched as output url.
Reading option '-v' ... matched as option 'v' (set logging level) with argument 'trace'.
Finished splitting the commandline.
Parsing a group of options: global .
Applying option v (set logging level) with argument trace.
Successfully parsed a group of options.
Parsing a group of options: input url sftp://byang@localhost:/home/byang/downloads/input.mp4.
Successfully parsed a group of options.
Opening an input file: sftp://byang@localhost:/home/byang/downloads/input.mp4.
[NULL @ 0x103800400] Opening 'sftp://byang@localhost:/home/byang/downloads/input.mp4' for reading
[sftp @ 0x101d03200] No default whitelist set
Process 24872 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
    frame #0: 0x0000000101adca15 libcrypto.1.0.0.dylib`HMAC_Init_ex
libcrypto.1.0.0.dylib`HMAC_Init_ex:
->  0x101adca15 <+0>: pushq  %rbp
    0x101adca16 <+1>: movq   %rsp, %rbp
    0x101adca19 <+4>: pushq  %r15
    0x101adca1b <+6>: pushq  %r14
Target 0: (ffmpeg) stopped.

Then, I break update and digest_update when HMAC_Init_ex is called. update provides the same function as digest_update, referring to the source code of libcrypto.

(lldb) b update
Breakpoint 2: 62 locations.
(lldb) b digest_update
Breakpoint 3: where = libboringssl.dylib`digest_update, address = 0x00007fff524364ed

Finally, update is called multiple times but digest_update is never called, before ffmpeg finishes normally with the error of not finding the nonexistent input.mp4.

......
//  `update` is called multiple times
......

(lldb) c
Process 24890 resuming
Process 24890 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 8.53
    frame #0: 0x0000000101b6f9cf libcrypto.1.0.0.dylib`update
libcrypto.1.0.0.dylib`update:
->  0x101b6f9cf <+0>: pushq  %rbp
    0x101b6f9d0 <+1>: movq   %rsp, %rbp
    0x101b6f9d3 <+4>: movq   0x18(%rdi), %rdi
    0x101b6f9d7 <+8>: popq   %rbp
Target 0: (ffmpeg) stopped.
(lldb) c
Process 24890 resuming
[libssh @ 0x101d02f60] Error opening sftp file: SFTP server: No such file
sftp://byang@localhost:/home/byang/downloads/input.mp4: Input/output error
Process 24890 exited with status = 1 (0x00000001)

The only difference between the lldb image list results of the two cases is:

[250] 4FCA5D2A-8885-3E57-9A9A-0D0D070356FA 0x00000001000de000 /Users/byang/project/opt/proxychains-ng/libproxychains4.dylib

libboringssl exists in both their dependent shared libraries.

Next step:

  1. Debug libcrypto of openssl with source code to figure out why digest_update is called.
rofl0r commented 6 years ago

can you paste the code from there ? Assertion failed: (ctx), function digest_update, file /BuildRoot/Library/Caches/com.apple.xbs/Sources/boringssl/boringssl-109.20.5/apple/crypto/digests.c, line 49.

singular78 commented 6 years ago

I google it and find that digests.c under the path /BuildRoot/Library/Caches/com.apple.xbs/Sources/boringssl/boringssl-109.20.5/apple/crypto/digests.c maybe not open-source and there is very little information about apple xbs.

The source code of digest.c of google's boringssl is digest.c of boringssl

rofl0r commented 6 years ago

that doesn't seem to be the right file though :/ even the copyright header there goes way beyond line 50...

singular78 commented 6 years ago

Apple may have changed the source’s copyright .

Is it normal that digest_update of libboringssl is called by libcrypto of openssl ?

rofl0r commented 6 years ago

i don't know, sorry.