PDA

View Full Version : RTMPDump patch for MyFreeCams


Edge
04-28-2013, 06:40 PM
After a bit of research I altered stock RTMPDump 2.4 to handle the MyFreeCams challenge/response system. More accurately, it's librtmp that is added to, since all rtmp/amf stuff really takes place there.

The patch comes with the following caveats:

It only works on *public rooms*.
You must have a socket connection to the chatserver *from the same IP* when you run RTMPDump. You can close it once you've latched onto the stream.
It sometimes fails to create the stream for no apparent reason. This is due to the fact that the "real" Flash client sends the subscribe/play in an Invoke of UpdateSession() from the server, whereas RTMPDump sends it immediately. To change this would require altering the basic way librtmp and RTMPDump work.
It assumes you've listened to the proper events and mapped camserv to videoserver as well as obtained a guest Session ID.
Output files still have broken timestamps, but a quick run through FFMpeg to transcode to your favorite container and codec will fix this without loss of parts or sped-up video anywhere. Audio is usually well synchronized.


Here it is:

diff -rupN diffrtmp/Makefile librtmp/Makefile
--- diffrtmp/Makefile 2013-04-28 20:18:42.000000000 -0400
+++ librtmp/Makefile 2013-04-28 19:59:47.000000000 -0400
@@ -24,7 +24,7 @@ DEF_GNUTLS=-DUSE_GNUTLS
DEF_=-DNO_CRYPTO
REQ_GNUTLS=gnutls
REQ_OPENSSL=libssl,libcrypto
-LIBZ=-lz
+LIBZ=-lz -lm
LIBS_posix=
LIBS_darwin=
LIBS_mingw=-lws2_32 -lwinmm -lgdi32
diff -rupN diffrtmp/rtmp.c librtmp/rtmp.c
--- diffrtmp/rtmp.c 2013-04-28 20:18:42.000000000 -0400
+++ librtmp/rtmp.c 2013-04-28 20:01:46.000000000 -0400
@@ -28,6 +28,7 @@
#include <string.h>
#include <assert.h>
#include <time.h>
+#include <math.h>

#include "rtmp_sys.h"
#include "log.h"
@@ -2904,6 +2905,33 @@ static const AVal av_NetStream_Publish_S
static const AVal av_NetConnection_Connect_Rejected =
AVC("NetConnection.Connect.Rejected");

+/* MyFreeCams challenge/response */
+static int HandleMfcChallenge(RTMP *r,int txn,int key) {
+ RTMPPacket packet;
+ char pbuf[1024],*pend=pbuf+sizeof(pbuf);
+ char auth[256],*enc;
+ AVal av;
+
+ RTMP_Log(RTMP_LOGINFO,"Responding to MFC challenge");
+ snprintf(auth,sizeof(auth),"%d",(int)floor(sqrt((double)key)*4));
+ av.av_val=strdup(auth);
+ av.av_len=strlen(auth);
+ packet.m_nChannel=0x03;
+ packet.m_headerType=RTMP_PACKET_SIZE_MEDIUM;
+ packet.m_packetType=RTMP_PACKET_TYPE_INVOKE;
+ packet.m_nTimeStamp=0;
+ packet.m_nInfoField2=0;
+ packet.m_hasAbsTimestamp=0;
+ packet.m_body=pbuf+RTMP_MAX_HEADER_SIZE;
+ enc=packet.m_body;
+ enc=AMF_EncodeString(enc,pend,&av__result);
+ enc=AMF_EncodeNumber(enc,pend,(double) txn);
+ *enc++=0;
+ enc=AMF_EncodeString(enc,pend,&av);
+ packet.m_nBodySize=enc-packet.m_body;
+ return RTMP_SendPacket(r,&packet,FALSE);
+}
+
/* Returns 0 for OK/Failed/error, 1 for 'Stop or Complete' */
static int
HandleInvoke(RTMP *r, const char *body, unsigned int nBodySize)
@@ -2912,6 +2940,10 @@ HandleInvoke(RTMP *r, const char *body,
AVal method;
double txn;
int ret = 0, nRes;
+ AMFObject mfcobj;
+ int challenge;
+ AVal av;
+
if (body[0] != 0x02) /* make sure it is a string method name we start with */
{
RTMP_Log(RTMP_LOGWARNING, "%s, Sanity failed. no string method in invoke packet",
@@ -2931,6 +2963,16 @@ HandleInvoke(RTMP *r, const char *body,
txn = AMFProp_GetNumber(AMF_GetProp(&obj, NULL, 1));
RTMP_Log(RTMP_LOGDEBUG, "%s, server invoking <%s>", __FUNCTION__, method.av_val);

+ av.av_val=strdup("key");
+ av.av_len=3;
+ if (!strcmp(method.av_val,"loginResult")) {
+ RTMP_Log(RTMP_LOGINFO,"MFC server sent challenge");
+ AMFProp_GetObject(AMF_GetProp(&obj,NULL,3),&mfcobj);
+ challenge=(int)AMFProp_GetNumber(AMF_GetProp(&mfcobj,&av,-1));
+ HandleMfcChallenge(r,txn,challenge);
+ return 1;
+ }
+
if (AVMATCH(&method, &av__result))
{
AVal methodInvoked = {0};


Put the above in a patchfile, say, mfc.patch, in the librtmp-directory (important! not in the rtmpdump directory) and run patch -p1 < mfc.patch, go up one level and make.

You still need to call RTMPDump with the appropriate parameters, as following:

rtmpdump -r rtmp://video434.myfreecams.com/NxServer -C S:42805804 -C S:'' -C S:102668880 -C S:DOWNLOAD -C S:2668880 -y mfc_102668880 -v -o CrumpetsNdTea_42805804.flv


I realize that this may not be terribly useful to *most* people, it's very rough around the edges, work in progress and so on. I also have a Flash-authored viewer that works flawlessly because it can emulate the "real" MFC client much more closely, but it's also fairly useless as a headless, unmonitored tool.

Why am I posting this? I'm not adverse to creating a more user-friendly tool but I have a job and like to not do much of anything in my spare time, so I'm hoping to be approached by some industrious people who have some knowledge of MFC and are willing to help out.

E.

yerman
05-23-2013, 02:52 AM
thanks for this however im getting a segfault core dumped, the binary appears to compile okay under ubuntu.

rtmpdump[10724]: segfault at bf997000 ip b77239ca sp bf990b14 error 6 in libc-2.15.so[b75f3000+19f000]

Update:

Adding the following removed the error:

export LD_LIBRARY_PATH=/usr/local/lib:/usr/lib

However im getting and error from mfc:

DEBUG: Property: <Name: level, STRING: error>
DEBUG: Property: <Name: code, STRING: NetConnection.Connect.Rejected>
DEBUG: Property: <Name: description, STRING: Connection failed.>
DEBUG: Property: <Name: application, OBJECT>
DEBUG: (object begin)
DEBUG: Property: <Name: message, STRING: You have been banned, or video unavailable>

Edge
05-24-2013, 06:55 AM
This happens when you haven't established a socket connection to the chat server. MFC checks and actually matches IP to ensure that whoever is connecting to the media server is also connected on the main site (which is a reasonable and smart way of doing things).

All you really need to do is telnet chat40.myfreecams.com port 80 (but this is not a HTTPD). Beware; it might time you out unless you send the proper connection string, which is "hello fcserver\n\0" followed by "1 0 0 20071025 0 guest:guest\n\0". Seeing as everything is terminated by "\0" I'm assuming this was originally supposed to be a Flash/AS3 xmlsocket:// connection, but it does use WebSockets if available, on the actual site.

E.

tural2010
10-21-2013, 01:49 PM
All you really need to do is telnet chat40.myfreecams.com port 80 (but this is not a HTTPD). Beware; it might time you out unless you send the proper connection string, which is "hello fcserver\n\0" followed by "1 0 0 20071025 0 guest:guest\n\0". Seeing as everything is terminated by "\0" I'm assuming this was originally supposed to be a Flash/AS3 xmlsocket:// connection, but it does use WebSockets if available, on the actual site.


Can you expand on that? I am interested in getting the list containing the online models. So here is what happened:


telnet
open chat40.myfreecams.com 80

It connects to the server. I quickly paste the two following commands.

send hello fcserver\n\0
send 1 0 0 20071025 0 guest:guest\n\0

A few seconds passes and the server sends a response.

HTTP/1.1 408 Request Time-out

It says that "Server timeout waiting for the HTTP request from the client." What am I missing here? I would to get the giant videomap too.

betoso01
12-05-2013, 04:40 PM
Hello,
I have a question. It is for EDGE, but anyone can answer. I am a beginner programmer. What technologies I have to learn to be able to: develop my own patch for rtmpdump, be able to analyze the network traffic in search of the correct parameters to use with rtmpdump and, finally, create a routine to automate the task of recording. My goal is to record live webcam sites